C++ Do-while loop stopping - c++

I got an assignment where we make a cmd prompt show up and display a flashcard game for multiplication. After inputting a correct answer a prompt shows up and asks the user to go "Again? Y/N." after the second input answer the prompt to ask the user doesn't show up and it's stuck on a "congratulations" message. This happens when I write in code to randomly generate two numbers for the game twice. one outside the while loop, and one inside while loop. If I leave one out the 2nd code for the random numbers it will run fine but will only display the same numbers over again. what I'm asking is how do I fix it so that it won't get stuck after the second answer input?
sample code below:
#include <iostream>
using namespace std;
int main()
{
int num1, num2, ans, guess, count = 0;
char choice;
num1 = rand() % 12 + 1;
num2 = rand() % 12 + 1;
//first number generator.
ans = num1 * num2;
do
{
{
cout << num1 << " X " << num2 << " = ";
cin >> guess;
cout << "Wow~! Congratulations~! ";
count++;
num1 = rand() % 12 + 1;
num2 = rand() % 12 + 1;
//second number generator.
} while (guess != ans);
cout << "\nAgain? Y/N: ";
cin >> choice;
} while ((choice == 'y') || (choice == 'Y'));
//after two turns the loop stops. Can't make a choice.
cout << " Thanks for playing! Number of tries:" << count << endl;
return 0;
}

I'd guess the problem is because your loops aren't quite what you think they are.
do
{
The code above has started a do loop.
{
I suspect you intended to start another (nested) do loop here--but you left off the do, so it's just a block that gets entered, executed, and exited. Useless and pointless in this case.
cout << num1 << " X " << num2 << " = ";
cin >> guess;
cout << "Wow~! Congratulations~! ";
count++;
num1 = rand() % 12 + 1;
num2 = rand() % 12 + 1;
//second number generator.
} while (guess != ans);
You've formatted this as if the while were closing the nested do loop--but since you didn't actually create a nested do loop, this is just a while loop with an empty body. Its meaning would be more apparent with a little re-formatting:
// second number generator
}
while (guess != ans)
/* do nothing */
;

The problem can be found here:
do
{
{
cout << num1 << " X " << num2 << " = ";
cin >> guess;
As you can see, the second scope has no do statement. As a result it is only a codeblock.
You can solve it by writing a do statement for the second code block.
Because the do is not present in the second bracket ({), the while is interpreted as a while loop:
while (guess != ans);
or
while (guess != ans) {
}
this thus keeps looping until guess is not equal to ans. But since in the loop does not modify any of the two variables, the loop will keep iterating.
Other errors: note that the program is still incorrect, since it will claim you have answered the question, regardless of the answer. You can fix it by implementing this as follows:
int main()
{
int num1, num2, ans, guess, count = 0;
char choice;
do {
num1 = rand() % 12 + 1;
num2 = rand() % 12 + 1;
ans = num1 * num2;
do {
cout << num1 << " X " << num2 << " = ";
cin >> guess;
if(guess == ans) {
cout << "Wow~! Congratulations~! ";
} else {
cout << "No, wrong!\n";
}
count++;
} while (guess != ans);
cout << "\nAgain? Y/N: ";
cin >> choice;
} while ((choice == 'y') || (choice == 'Y'));
//after two turns the loop stops. Can't make a choice.
cout << " Thanks for playing! Number of tries:" << count << endl;
return 0;
}

Related

Clearing input buffer

I am writing a program, the program is basically a guessing game. Computer displays a number and the user has to guess whether their number is higher, lower or correct. I have already made the program and its all dandy, but the only not dandy part is that I cannot figure out how to get rid of the input buffer when the user decides to play the game again. Every time the user wants to play the game, the game starts again but with the same input as the last game. I have tried putting cin.clear() in any spot I could think and also cin.clear(). But it just seems to not work. How do I clear the input?
#include <iostream>
using namespace std;
int main ()
{
int num1 = 100;
char choice;
num1 = num1 / 2;
do
{
cout << "My guess is " << num1 << ". " << "Enter 'l' if your number is lower, 'h' if it is higher, 'c' if it is correct: ";
cin >> choice;
cin.clear();
if (choice == 'h')
{
num1 = num1 + 100;
num1 = num1 / 2;
}
if (choice == 'l')
{
num1 = num1 + num1;
num1 = num1 - 11;
num1 = num1 / 2;
}
if (choice == 'c')
{
cout << "Great! Do you want to play again (y/n)?: ";
cin >> choice;
}
} while (choice != 'c' || choice == 'Y' || choice == 'y' || choice == 'n' || choice == 'N');
return 0;
}
In order to restart the game, you need to reset num1. Put the inital value in a variable that you don't change.
const int init = 100;
char choice;
int num1 = init / 2;
When the computer has guessed correctly:
if (choice == 'c')
{
num1 = init / 2; // reset
cout << "Great! Do you want to play again (y/n)?: ";
cin >> choice;
}
You could also leave the loop condition at:
} while(choice != 'N' && choice != 'n');
You should also work on the divide and conquer algorithm. For the computer to be effective, it should always make a guess in the middle of the range that is still possible, and that's not what it's doing right now. It jumps up and down, even outside the established range. An alternative could be to keep two variables to be able to shrink the possible range effectively. You could also do two separate loops, one inner loop for guessing the number and one outer that only asks the user if he/she wants to play again.
Example:
#include <iostream>
int main() {
const int initlo = 1;
const int inithi = 100;
char choice;
do {
std::cout << "Think of a number [" << initlo << "," << inithi << "]\n";
int numlo = initlo; // initialize the range
int numhi = inithi;
int guess;
do {
guess = (numlo + numhi) / 2; // guess in the middle of the range
std::cout
<< "My guess is " << guess << ". "
<< "Enter 'l' if your number is lower, 'h' if it is higher, 'c' "
"if it is correct: ";
std::cin >> choice;
if(choice == 'h') // must be in the range (guess,numhi]
numlo = guess + 1;
else if(choice == 'l') // must be in the range [numlo,guess)
numhi = guess - 1;
// exit the loop if the user cheats or the answer is correct
} while(numlo <= numhi && choice != 'c');
if(choice == 'c') std::cout << "Great! ";
else std::cout << "Cheater! ";
std::cout << "Do you want to play again (y/n)?: ";
std::cin >> choice;
} while(choice == 'Y' || choice == 'y');
std::cout << "Bye\n";
}

Unexpected loop behaviour in c++

// cai.cpp (Computer Assisted Instruction)
// This program uses random number generation to assist students learn multiplication
#include <iostream>
#include <iomanip>
#include <cstdlib> // contains prototypes for srand and rand
#include <ctime>
#include <cctype>
using namespace std;
int main() {
int question();
string status;
int score{0};
cout << "\nThis program will present you with 10 multiplication problems\n"
<< "enter the correct answer after the prompt\n"
<< "Enter Y for YES and N for NO\n"
<< "Do you want to try a game?";
cin >> status;
while(status == "Y" || status == "y") {
for(int x{0}; x < 11; x++) {
question();
score = score + question();
}
// report total score
cout << "\nTotal score is " << score << " out of 10";
cout << "\nWould you like to play again?";
cin >> status;
if(status == "n" || status == "N") {
break;
}
}
cout << endl;
}
int question() {
string responses();
// use srand to generate the random nmber for the various problems
srand(static_cast<unsigned int> (time(0)));
int number1 = 1 + rand() % 12; // initialize random number
int number2 = 1 + rand() % 12; // initialize random number
int total = number1 * number2;
int response;
int score{0};
cout << "\nWhat is " << number1 << + " times " << + number2 << + " ?";
cin >> response;
while (response != total) { // while answer is wrong, repeat question and wait for response
cout << " \nThat is incorrect, try again: ";
cin >> response;
}
if ( response == total) {
cout << responses();
score++; // increment score after each correct answer
}
return score;
}
string responses() {
string res1 = "Well done, that is correct!\n";
string res2 = "Congratulations, that is very accurate!\n";
string res3 = "Wow!, I'm impressed\n";
string res4 = "You're doing great! Keep up the good work.\n";
srand(static_cast<unsigned int> (time(0)));
int select{1 + rand() % 4};
switch(select) {
case 1: return res1;
break;
case 2: return res2;
break;
case 3: return res3;
break;
case 4: return res4;
break;
default: return " ";
}
}
When I compile and run this program, I expect it to loop only 10 times but it loops more than 10 times, I'm thinking it has to do with the switch statement in the responses function but I do not understand why it should be causing a problem. Any explanation would be greatly appreciated. I have modified the while loop condition in the main function to loop different times but it always loops to display all the possible responses in the switch statement. Screen shot of results attached, I modified the while statement to loop only twice but I still had all my responses showing so it ended up looping 4 times.
expect it to loop only 10 times but it loops more than 10 times
In your loop:
for(int x{0}; x < 11; x++)
x goes from 0 to 10, so it loops 11 times.
A few things to note. Your for loop goes up to < 11, meaning 10. So x from 0 to 10 (inclusive) is actually 11 times. You need to change the condition to < 10, or change x to start at 1.
Second issue, inside the for loop, you are actually calling the question function twice; with the first call's result being ignored. This is why you are getting 4 questions, each answered correctly, but only a score of 2.
Third, not so much an issue, but a bit redundant. At the end of the while loop, you check status == "n" || status == "N", however, this is unnecessary, since the while loop's condition checks for y and Y already.
I've cleaned up your while loop a bit here:
while(status == "Y" || status == "y") {
for(int x = 0; x < 10; ++x) {
score += question();
}
// report total score
cout << "\nTotal score is " << score << " out of 10";
cout << "\nWould you like to play again?";
cin >> status;
}
Unrelated thing to also clean up. You don't need to call srand in the question() function, instead just call it once in main. Also, since this is C++, you can use newer random generators from the <random> header.

C++ total keeps going up

Hello this is my first program with a do-while loop and its taken me a little while to get it down. I need to have the user enter 2 numbers, and raise the first number to the second number. I have finally got the coding to ask if "they would like to raise another number by a power?" and when they say yes and enter 2 new numbers the total adds the total from the first 2 numbers entered with the second set of numbers and so on. Can someone help me out with this problem? Here is the coding and a picture to help y'all out!
#include <iostream>
using namespace std;
int main()
{
int num;
int pow;
int p;
int power = 1;
char yesno = 'y' || 'Y';
do
{
cout << "Enter a number: ";
cin >> num; "\n";
cout << "Enter the power to raise: ";
cin >> pow; "\n";
for (p = 1; p <= pow; p++)
{
power = power * num;
}
cout << "The total is: " << power << endl;
cout << "\n\n";
cout << "Would you like to raise another number by a power? [Y/N]";
cin >> yesno;
} while (yesno != true);
}
The problem of the ever-increasing answer is that power is not being reset inside the do-while loop, so the last value is being carried forward into the next loop. You need reset it at the top of the loop.
Another problem with the code is that the exit condition would never occur.
Try this instead:
int main()
{
int num;
int pow;
int p;
int power;
char yesno;
do
{
power = 1; // <<<<<< reset power here
cout << "Enter a number: ";
cin >> num; "\n";
cout << "Enter the power to raise: ";
cin >> pow; "\n";
for (p = 1; p <= pow; p++)
{
power = power * num;
}
cout << "The total is: " << power << endl;
cout << "\n\n";
cout << "Would you like to raise another number by a power? [Y/N]";
cin >> yesno;
} while (yesno == 'y' || yesno == 'Y'); // <<<<< test for 'yes' response
}
When you reach line } while (yesno != true); and loop back to do {, the variable power still holds the previous num^pow. You will need to assign power = 1 after do {.
#include <iostream>
// you also need
#include <cmath> // for pow()
using namespace std;
int main()
{
// int num; Declare variables where they're used. As locally as possible.
// int pow;
// int p;
// int power = 1;
// char yesno = 'y' || 'Y'; I don't know what you were trying to do here
// the expression 'y' || 'Y' will always be true
// and evaluate to some value different from null
// wich will be assigne to yesno. But with no con-
char yesno; // sequences since it later gets overwritten by
do // cin >> yesno; There is no need to initialize
{ // this variable.
cout << "Enter a number: ";
int num;
cin >> num; "\n"; // the statement "\n"; has no effect.
cout << "Enter the power to raise: ";
int pow;
cin >> pow; "\n"; // again. no effect.
// for (p = 1; p <= pow; p++) as user4581301 has pointed out in the
// comments it is more ... natural in C
// to loop from 0 to < max:
int power = 1; // now its time to declare and define power ;)
for(int p = 0; p < pow; ++p) // notice that you can declare variables
{ // in the init-statement of a for-loop
// power = power * num; shorter:
power *= num;
}
cout << "The total is: " << power << /* endl; + 2 x '\n' gives: */ << "\n\n\n";
// cout << "\n\n";
cout << "Would you like to raise another number by a power? [Y/N]";
cin >> yesno;
// } while (yesno != true); that condition will most likely always be true
// since the user would have a hard time to input
// a '\0' character, which would evaluate to false
// better:
} while(yesno == 'y' || yesno == 'Y' );
}
done.
Without clutter:
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
char yesno;
do {
cout << "Enter a number: ";
int num;
cin >> num;
cout << "Enter the power to raise: ";
int pow;
cin >> pow;
int power = 1;
for(int p = 0; p < pow; ++p)
power *= num;
cout << "The total is: " << power << "\n\n\n";
cout << "Would you like to raise another number by a power? [Y/N]";
cin >> yesno;
} while(yesno == 'y' || yesno == 'Y' );
}

Programming Principles and Practice: chapter 4 drill part 1

I just can't seem to get this program to work properly. I can get it to accept two integers and print them to the screen. But I can't get the program to terminate when the '|' is used. Once that its entered it loops infinitely. Here is the code that I have so far:
#include "../../std_lib_facilities.h"
int main()
{
int num1 = 0;
int num2 = 0;
char counter = '\0';
cout << "Please enter two integers and press enter. \n";
bool test = true;
while (counter != '|')
{
cin >> num1 >> num2;
cout << "Your numbers are: " << num1 << " " << num2 << endl;
if (cin.fail())
{
cout << "Goodbye!\n";
test = false;
}
else (counter != '|');
cout << "Enter more numbers or press '|' to exit.\n";
}
system("pause");
}
You are using the wrong condition in your while loop. You are never changing counter so the loop will never end. However you do change test to false in the while loop if the input fails. You can change the condition of the while loop to use test instead like
while(test)
{
//...
}
Since counter is no longer being used you can get rid of it completely.
Please note that unless you change to taking in string and parsing the input any input that will cause cin to fail will end the loop not just a |.

C++: Asking the user to enter a new number if the number they entered is wrong

I'm trying to get the program to loop again, up to three times, if the user entered a number that does not follow the function defined in the if statement. The code as is, only loops once and then exits. Did I type the for loop incorrectly or is it the if...else statement that is wrong?
#include <iostream>
using std::cout; using std::cin; using std::endl;
int main() {
cout << "Enter a positive odd number less than 40: ";
int num = 0;
for (int a = 0; a < 3; ++a);
cin >> num;
{
if (num < 40 && num > 0 && num % 2 == 1)
{
cout << "Thank you!" << endl;
}
else cout << "That is incorrect, try again!" << endl;
}
}
Did I type the for loop incorrectly or is it the if...else statement that is wrong?
Both. You should (1) remove the semicolon following the for statment; (2) move cin >> num into the for loop body; (3) add break; inside the if.
for (int a = 0; a < 3; ++a)
{
cin >> num;
if (num < 40 && num > 0 && num % 2 == 1)
{
cout << "Thank you!" << endl;
break;
}
else cout << "That is incorrect, try again!" << endl;
}
BTW1: Try to use the debugger, then you'll find out what happened in fact.
BTW2: The code will fail when cin >> num fails (e.g. user entered an invalid value), you might need to check the result of cin >> num, to process the case. Such as:
for (int a = 0; a < 3; ++a)
{
if (cin >> num)
{
if (num < 40 && num > 0 && num % 2 == 1)
{
cout << "Thank you!" << endl;
break;
}
else cout << "That is incorrect, try again!" << endl;
}
else
{
cin.clear(); // unset failbit
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // skip bad input
cout << "Wrong input, try again!" << endl;
}
}
bool isValid = false;
int num;
while(!isValid)
{
cout << "enter a positive odd integer " << endl;
cin >> num;
if(num < 40 && num > 0 && num % 2 == 1 )
{
cout << "thank you"<<endl;
isValid = true;
}
else
isValid = false;
}
Why not use some thing like this, it will loop until isValid = true which will only happen when your conditions are met?
I understand I guess, if you're doing a school project or some thing and you're forced to do it with a for loop but in general this would be a much better solution for some thing like this than a for loop!