Why does this do/while never end? - c++

It just keeps looping. The numbers continue decreasing until the program is closed. Am I misusing something?
The playerHealth and orcHealth ints are 100.
randomNumber = ("%10d", 1 + (rand() % 100));
This was the way I seen the random number used on an srand() explanation page. If this is wrong, how should it be?
Are there any other problems here?
switch(charDecision)
{
case 1:
cout << "FIGHT" << endl;
do{
randomNumber = ("%10d", 1 + (rand() % 100));
if(randomNumber >= 50){
orcHealth = orcHealth - (randomNumber - (randomNumber / 5));
cout << "You hit the orc! He now has " << orcHealth << " life left!" << endl;
}
else
{
playerHealth = playerHealth - (randomNumber - (randomNumber / 5));
cout << "The orc hit you! You now have " << playerHealth << " life left!" << endl;
}
}while(playerHealth || orcHealth >= 0);
break;
default:
break;
}

playerHealth || orcHealth >= 0 does not mean "while playerhealth greater than zero OR orchealth greater than zero". It means "while playerhealth, cast to boolean is true OR orchealth greater than zero".

This
}while(playerHealth || orcHealth >= 0);
should probably be
}while(playerHealth > 0 && orcHealth > 0);
I think you want to exit the loop, if either one is 0 or less.
Also, change randomNumber = ("%10d", 1 + (rand() % 100)); to randomNumber = 1 + rand() % 100;
The comma operator just obfuscates the code.

Your condition for the do...while statement will stop at some point, but only at some point. This means, your condition will be met if either playerHealth is zero or orcHealth is smaller than zero. What if the playerHealth gets below zero? This is very likely since you are always deducting a number from both character's healths. A possibility of playerHealth becoming exactly zero is a very tiny one. And when the playerHealth goes below zero, its possibility of becoming zero is still very unlikely, even due to integer overflow. So, if you want to "kill" the character when one of their health becomes zero or less, you better change that line with something like
while ( playerHealth > 0 && orcHealth > 0 )
On a side note, the || statement works if any one of the statements is true. In C++, for an integer a 0 value is false, all other values -including negative ones- are treated as true. Also, the || checks from left to right and when it finds the first true statement, it stops searching. In your case, it checks playerHealth, which is very likely nonzero. When it sees this expression is true, it decides that the whole statement inside the parantheses is true and skips checking orcHealth >= 0. This results in the infinite loop. You might want to look at the order of evaluation of conditionals in C++, maybe something like this post.

Related

Why is 100 not inclusive in this program?

I am writing this program which will guess the number user is thinking about. After days of work, I could not figure out what is wrong in it.
Also my proposed grade for the assignment is not what I expected.
Please help.
User can guess 100, but my program uses mid-point rule so can only go up to 99. How can I make 100 inclusive?
If I keep pressing 'l' the program will eventually break out of loop and prints If you want to try again?
Is there a better way to code this program? Example please.
Here is the actual program:
Write a program in that can figure out a number chosen by a human user. The human user will think of a number between 1 and 100. The program will make guesses and the user will tell the program to guess higher or lower. The program should find the midpoint of the two numbers and ask if the number is higher or lower.
#include <iostream>
using namespace std;
int main() {
char check;
char tryagain;
do {
int midpoint;
const int MAX = 100;
const int MIN = 1;
int y = MAX;
int x = MIN;
cout << "Think of a number between 1 and 100." << endl;
midpoint = (x + y) / 2;
while (x != y || y != x) {
cout << endl << "Is it" << " " << midpoint << " " << "?";
cin >> check;
if (check == 'l' || check == 'L') {
y = midpoint;
midpoint = (x + y) / 2;
}
else if (check == 'h' || check == 'H') {
x = midpoint;
midpoint = (x + y) / 2;
}
else if (check == 'c' || check == 'C') {
break;
}
else {
cout << "Incorrect choice." << endl;
}
}
cout << "Great! Do you want to try again? (y/n)";
cout << endl;
cin >> tryagain;
} while (tryagain == 'y' || tryagain != 'n');
return 0;
}
Your problem is just a mis-think in the calculation of x and y like Alf suggested in the comments.
It should read
y = midpoint - 1;
and
x = midpoint + 1;
respectively. The reason is simple. You use midpoint as the guess. The guess is then no longer part of the available guesses. Your first guess is 50, x or y should then be either 51 or 49 as the new min or max in the interval.
This will also make 100 included in the available guesses. The last step in the calculation will be when midpoint was 99 and the user selects 'h'.
x = 99 + 1;
lower bound is 100, and the midpoint guess evaluates to
midpoint = (100 + 100) / 2;
which is correct.
As for better ways to write this program. This would depend on what your course has taught you, what's in the curriculum, and so on. You might want to check out code-review
When your x and y are too close, the division of their sum produces an incorrect midpoint. 100 + 99 / 2 = 99 (which is 99.5 rounded down). You need to check for this special case. At the end of the loop before the closing bracket insert:
if ( y-x < 2) midpoint = y;
User can guess 100, but my program uses mid-point rule so can only go up to 99. How can I make 100 inclusive?
Division of integers in c++ discards any decimal. It always rounds down. Consider what happens when midpoint is 99. You get midpoint = (99 + 100) / 2 which is 199 / 2 which is 99.5. Discarding the decimal leaves you with 99 every time. One possible solution is to change y = midpoint; to y = midpoint - 1; and x = midpoint; to x = midpoint + 1; This will prevent your application from guessing the same value more than once. With this change, when midpoint is 99, x will first be incremented to 100 giving us a new midpoint (100 + 100) / 2 which evaluates to 100.
If I keep pressing 'l' the program will eventually break out of loop and prints If you want to try again?
If the user keeps pressing l then eventually the only possible solution is 1. It seems that you chose not to propose your guess at that point and assume the user followed the rules. Add an extra print when the answer is deduced.
if (x == y) {
// Answer was deduced
cout << "You guessed " << x << ".\n";
}
Is there a better way to code this program? Example please.
See the first two parts of this answer. Other than that, it's difficult to say objectively what "better way to code this" means. You might want to consider a system to detect when the user is lying. For example, if midpoint == x then the user can't select l without lying.

Recursion and pre-decrement operator

I have this function:
void m(int n)
{
if(n > 0)
m(--n);
cout << n << " "; //for n = 5 --> output is: 0 0 1 2 3 4
}
I have a problem with understanding how it works.
For example:
n(input) = 5
output: 0 0 1 2 3 4
My question is: Why does it show zero twice?
When I add brackets like this:
void m(int n)
{
if(n > 0)
{
m(--n);
cout << n << " "; // now, it shows 0 1 2 3 4 (n = 5)
}
}
So, what brackets cause in this code, that "0" exists only once?
And when I change pre-decrement (--n) to post-decrement (n--) it shows nothing. Why?
Could somebody help me to understand how it works?
First thing to note is : in C++ if you don't put brackets after an if statement, only the next line will be in the statement.
Example :
if(x > 0)
cout << 1;
cout << 2;
Here cout << 2 will always be executed no matter the value of x
The correct way of writing this is
if(x > 0)
{
cout << 1;
cout << 2;
}
Same thing goes for else statements
So this was for the brackets.
My wild guess for the post decrement is the following :
if you do m(n--), the value passed will be 5, the value of n will only change after the function call and go out of scope (so it won't matter). So what will happen is an infinite number of m(5) calls and that's why nothing is appearing. (I'm not sure about that part so please tell me if wrong) !
Hope it helped !
Looks like you confused with Python syntax, where scope of if is determined by indent. In C (and C++, C#, Java an many other languages) the scope is one statement (which ends with ;) unless you use curly brackets { and }. In the 1st variant of your code cout << n << ... will be always performed, regardless of value of n. In second variant it will be performed only if(n > 0)

C++ do while not looping

I understand I can just use for-loop to define prime number, but before I implement for loop into that topic, I had a thought that I maybe could make one with while loop or do-while.
Somehow, my do-while loop seems not to be working correctly.
My theory was that I could find prime number for checking the remainder of divisor where divisor keeps decreasing by 1 until divisor reaches 1. (Although 'until divisor reaches 1.' part is not in the code, I would assumed remainder of 0 would appear anyway before divisor goes below 0.)
However, it keeps halting before remainder reaches 0.
What did I do wrong?
I've even tried both instead of (remainder<1 && remainder!=1)below but still no luck.
while (remainder<1)
while (remainder==1)
#include <iostream>
using namespace std;
int main()
{
int number, divisor, remainder;
cin >> number;
divisor=number-1;
cout << "You've put " << number << ".\n";
do {
divisor = divisor - 1;
remainder=number%divisor;
}
while (remainder<1 && remainder!=1);
cout << divisor << " " << remainder << " " << number << " " << "Divisor, remainder, number\n";
return 0;
}
First, you have a typo in your variable assignment. This line:
number = divisor - 1;
should be:
divisor = number - 1;
The while() condition should be while (remainder != 0), so that the loop keeps repeating as long as you haven't found a divisor. If you want to be more explicit, you could use while (divisor > 1 && remainder != 0). There's no need to repeat when divisor == 1 because that's a divisor of all integers.

. Read in real numbers until 10 positive values have been found. Write out the sum of the 10 positives

Here's the important part of my code:
int realnum, positive = 0, total, poscount;
for (poscount = 1; poscount < 11; poscount++)
{
cin >> realnum;
while (realnum > 0)
{
total = realnum + positive;
}
}
cout << "Total of 10 positive values is " << total << endl;
I really just don't see what's wrong here. After declaring my integers the program goes into my for, increase the poscount to 2, asks my to input realnum. I put in a positive number (ex: 6), which should in theory add my realnum with positive (which I declared 0) and give total the value (ex: 6 + 0 = 6). It should keep looping until poscount reaches 11 and output the total of 10 positive numbers.
When I run it, I put in 6 and the command prompt just shows 6, nothing happens, and I have to close through the x button. Can someone please tell me what the error is?
I would just use a while in the outer loop, to keep the number of so-far positive numbers.
Also, your total is uninitialised and you assign positive to it, which is just 0?
This is what I have in mind:
int realnum, total = 0, poscount = 0;
while (poscount < 10) {
cin >> realnum;
if (realnum > 0)
{
total += realnum;
poscount++;
}
}
cout << "Total of 10 positive values is " << total << endl;
Replace your while with an if since currently, once you enter that while loop you never exit it.
Also, why are you always increasing poscount? Shouldn't you only do that if realnum is positive? The iteration statement in the for loop is allowed to be blank; then you write poscount++ inside the new if block.
You also need to write total += to increment the total amount.
These things are easy to spot if you use your debugger.
Okay, so I think I've corrected myself (without blatantly copying blurry but also using Bathsheba's tip on replacing my while.
int realnum = 1, positive = 0, total, poscount;
if (realnum > 0)
{
for (poscount = 1; poscount < 11; poscount++)
{
cin >> realnum;
total = realnum + positive;
positive = total;
}
}
cout << "Total of 10 positive values is " << total << endl;
So far, it seems to work, there's probably a lot of unnecessary things that make it inefficient but I didn't want to copy examples. *Edit of course I still need to do with the ignoring negative part
I think I backed myself into the point of no return, ha. I really thought there was an alternate way I was going... Anyways, thanks for your replies, guys. I've always been lurking around here, until I made an account now.
Add a condition to terminate the while loop. And instead of adding positive to realnum, try adding poscount. That should provide the desired result.

probability c++ question

I have to make a game of craps and towards the end, I have to do some probability. Here is my code so far. I want it so that the loop repeats 1000 times and looks for the 'probNumb' that the user entered. I am not sure if did this right but lets say I entered the number 5. This is what I get.
"Out of 1000 times, 5 was rolled 1000 times."
So, its not counting how many times 5 was rolled. I am not allowed to use break or continue statements, only loops and if else.
cout &lt&lt "What number do you want the probability of ?";
cin >> probNumb;
while (probCount &lt 1000)
{
ranNumb= 1 + (rand() % (5 + 1));
ranNumb2= 1 + (rand() % (5 + 1));
ranNumbFin = ranNumb + ranNumb2;
probCount++;
if (ranNumbFin = probNumb)
probNumbCount++;
}
cout &lt&lt "Out of 1000 times, " &lt&lt probNumb &lt&lt " was rolled "
&lt&lt probNumbCount &lt&lt "times." &lt&lt endl;
if (ranNumbFin = probNumb) is either a typo or should use ==
It's 1000 because the assignment returns the value assigned and since that's always non-zero in this case, it's always true.
it's a typo
if (ranNumbFin = probNumb)
should be
if (ranNumbFin == probNumb)
Your line if (ranNumbFin = probNumb) should be if (ranNumbFin == probNumb) - you're assigning, not comparing, which is causing the probNumbCount to increment every time.
My use of C and C++ is rusty, but I believe the ranNumb and ranNumb2 are not going to behave like dice rolls. These will just give a uniform random variate over 0 to 1.
Conceptually, for a six sided dice:
u = rand();
if(u < 1/6) ranNumb=1;
elseif(u < 2/6) ranNumb=2;
elseif(u < 3/5) ranNumb = 3;
An so on. There is probably a better performing method.