# Validating an input to be a number for guessing game

Show 80 post(s) from this thread on one page
Page 1 of 2 12 Last
• 11-02-2007
Molokai
Validating an input to be a number for guessing game
Finally, an update to the number guessing game. I've come back to it after all this time, and had to start from scratch (because of upgrading to Vista, which I'm not sure if I regret or not). However, I think I got a better result anyway, as this time, I not only managed the loop for replay, I put in a minor menu, added difficulty settings, and put in a number validation sequence to make sure the number input is in the given range. Here's what I've got:
Code:

```#include <cstdlib> #include <ctime> #include <iostream> using namespace std; //returns value between 0 and RAND_MAX //rand(); //srand (time(0)); int x,w,random,guess,tries,option; char play; int game (){     do {         cout << "\nEnter a difficulty level: \n1. Easy\n2. Medium\n3. Hard\n4. Very Hard\n5. Insane!\n\n";//States possible difficulties         cin >> w;         if (w==1) x = 50;         if (w==2) x = 100;         if (w==3) x = 500;         if (w==4) x = 1000;         if (w==5) x = 10000;//Determines upper limit for random generator         srand(time(0));//Random seed         random = rand() &#37; x + 1;//Random number generation         cout << "\nNumber chosen between 1 and " << x << ".\n";         cout << "Enter your guess.\n";         cin >> guess;         tries = 1;//Sets tries to one after first guess before going into the game loop         while (guess != random){             if ((guess > x) && (guess < 1)) {                 cout << "\nIllegal guess.  Your guess must be between 1 and " << x << ".\n";//Keeps player from inputting a number that is not available                 --tries;//Sets counter back to keep track of legal guesses only             }             else if (guess > random)                 cout << "\nYou guessed too high.\n";             else                 cout << "\nYou guessed too low.\n";//The actual process of guessing the number                 cout << "Enter your guess.\n";                 cin >> guess;                 ++tries;         }             cout << "\nYou Guessed It!\n";             cout << "You took " << tries << " guesses.\n";//Displays number of legal guesses required to win current round             cout << "Would you like to play again (Y/N)?\n";//Asks if player wants to play again, feeds into do...while loop parameter             cin >> play;     } while (play == 'y');     return 0; } int menu(){     cout << "Main Menu: \n1. New Game \n2. Quit\n";     cin >> option;     if (option == 1)         game();     else         return 0; } int main(){     cout << "Welcome to Guess It, the number guessing game.\n";         menu();         return 0; }```
Now, right now I have two problems.
1) I can't find any reasonable resource for validating the input as a number, instead of a letter or punctuation. I've tried something like this:
Code:

```cin.ignore(numeric_limits<int>::max(), '\n');         while (guess != random){             if (!cin || cin.gcount() != 1){                 cout << "\nIllegal guess.  Your guess must be a number.\n";```
As the first if... statement in the game loop, but although it works and it displays the "Illegal guess" line and the "enter your guess" line later, it does it on an infinite loop, and I can't get it to do it just once and accept another input.
2) I don't know how to make it go back to the menu after the player says "no" to the play again question.

Any and all help will be greatly appreciated.

Edit: OK, I got the menu to work. All I needed to do was add a parameter (I chose on) to tell whether or not the program was supposed to still be running. I then put a do...while loop in main() to keep going back to the menu as long as on == 1. I then put an extra line in menu() to say if the player doesn't want to start a new game, but instead wants to quit, on is set to 0. So, the changes look like so:
Code:

``` int menu(){     cout << "Main Menu: \n1. New Game \n2. Quit\n";     cin >> option;     if (option == 1)         game();     else         on = 0;     return 0; } int main(){     cout << "Welcome to Guess It, the number guessing game.\n";         do {             menu();         } while (on == 1);         return 0; }```
Still need help on the letter elimination problem...
• 11-02-2007
Daved
This is how I normally check input to see if its a number:
Code:

```while (!(cin >> guess)) {   cin.clear(); // clear fail state   cin.ignore(numeric_limits<int>::max(), '\n'); // ignore bad input   // prompt again here. }```
You can add to the while control more checks. For example, to error on 123abc add a check for cin.get() != '\n', and to check for numbers in your range add those as well.
Code:

`while (!(cin >> guess) || cin.get() != '\n' || (guess > x) || (guess < 1))`
Note that I used logical OR, not AND, since you want to enter the loop if any of the reasons for error are true (rather than only entering the loop if all of them are).

>> 2) I don't know how to make it go back to the menu after the player says "no" to the play again question.
You need a loop around the menu code.
• 11-02-2007
Molokai
That's what I did. And, just to clarify, the only reason I wanted a menu was because I wanted to start using a high scores page, and I have no idea how to do that at all. Can't find anything online about doing that. Any help there would be useful, too.

By the way, Daved, that worked almost perfectly, except that now it doesn't recognize any odd number...
• 11-02-2007
Molokai
Never mind, it's not that it doesn't recognize odd numbers, it just doesn't recognize every other input. Say I put in 25 for my first guess. it tells me whether I'm high or low. Then I enter my next guess, and whether it's 15 or 36, it just stays blank until I put another guess in.:confused:
And, on top of that, it doesn't add to the number of tries for each blank response. It only adds to it when it recognizes an input and gives the try again output. And, if you guess the right number on what should be an unrecognized guess input, it recognizes it and you win the game...
• 11-02-2007
Daved
Can you show what you tried?

Note that I moved the input into the while control, so you should remove the cin >> guess line in your current code.
• 11-02-2007
Molokai
Oh, I didn't realize that that is what that did.
I've been fidgeting with the code, and came up with this:
Code:

```int game (){     do {         cout << "\nEnter a difficulty level: \n1. Easy\n2. Medium\n3. Hard\n4. Very Hard\n5. Insane!\n\n";//States possible difficulties         cin >> w;         if (w==1) x = 50;         if (w==2) x = 100;         if (w==3) x = 500;         if (w==4) x = 1000;         if (w==5) x = 10000;//Determines upper limit for random generator         srand(time(0));//Random seed         random = rand() % x + 1;//Random number generation         cout << "\nNumber chosen between 1 and " << x << ".\n";         cout << "Enter your guess.\n";         tries = 0;         while (guess != random){             if (!(cin >> guess)) {                 cin.clear(); // clear fail state                 cin.ignore(numeric_limits<int>::max(), '\n'); // ignore bad input                 cout << "\nIllegal guess.  Your guess must be a number.\n";                 --tries;             }             else if ((guess > x) || (guess < 1)) {                 cout << "\nIllegal guess.  Your guess must be between 1 and " << x << ".\n";//Keeps player from inputting a number that is not available                 --tries;//Sets counter back to keep track of legal guesses only             }                 else if (guess > random)                 cout << "\nYou guessed too high.\n";                 else                 cout << "\nYou guessed too low.\n";//The actual process of guessing the number                     cout << "Enter your guess.\n";                     ++tries;         }             cout << "\nYou Guessed It!\n";             cout << "You took " << tries << " guesses.\n";//Displays number of legal guesses required to win the round             cout << "Would you like to play again (Y/N)?\n";//Asks if player wants to play again, feeds into do...while loop parameter             cin >> play;     } while (play == 'y');     return 0; }```
You'll notice I had to define tries as 0 instead of 1, since no guesses had yet been made, and I had to declare it within the game, otherwise it just kept adding to the previous successful total guesses. I also remembered to remove the "cin >> guess;" from within the loop itself, to make sure there was only one.

I also had to made the while into an if, and put the rest int else...if's or else's. The reason for this is because if it was a while, it just kept subtracting from the number of tries, without the "++tries;" at the end of the loop balancing it out, resulting in skewed tries numbers.

Now, while all of this now works perfectly, there is still one problem: If someone puts in a decimal, such as 1.5, it registers as a legal number at first, and gives the ++tries; then, when it gets back to the beginning of the loop, it says the same guess was illegal, and then does both the --tries; and the ++tries; resulting in an added try, despite the fact it should be illegal. What can I do about that? Maybe a parameter I could put in the while loop to make it look for decimals in the middle of the numbers? Or to look for floats?
• 11-02-2007
Salem
Code:

```                else if (guess > random)                 cout << "\nYou guessed too high.\n";                 else                 cout << "\nYou guessed too low.\n";//The actual process of guessing the number                     cout << "Enter your guess.\n";                     ++tries; ```
Despite your excellent indentation, the two red lines are NOT part of the final else.

ALWAYS use braces to make your intention explicit, then you'll never fall into the trap of changing one statement into several statements, and the code breaking because you forgot the now compulsory braces.
• 11-02-2007
Molokai
Those last two lines aren't meant to be part of the last else. They're meant to do exactly what I programmed them to do, which is to execute no matter which of the if's was executed. And it's supposed to look like this:
Code:

```        else if (guess > random)                 cout << "\nYou guessed too high.\n";         else                 cout << "\nYou guessed too low.\n";//The actual process of guessing the number             cout << "Enter your guess.\n";             ++tries;```
• 11-02-2007
Daved
Putting it into the if instead of a while the way you did is fine (and you did a good job of taking the example and adapting it to your purpose).

Now, you have two similar issues. What if the user types 1.5, and what if the user types 123abc. Either way, the code will read in a number, then stop at the '.' or the 'a' (or any non-numeric character), which will break it the next time through.

You have two choices to handle this. Do you want to allow the guess and ignore the rest of the line, or do you want to give an error message. For example, if the user inputs 1.5, you could read in the 1 and ignore the rest, or you could just make the whole thing an error. I prefer the second option, but it's up to you.

For the first option, just always add the ignore() line of code no matter what (take it out of the first if and move it to the bottom outside the if/else if/else statements. That way it will always ignore leftover characters.

The second option is to add a new else if (probably immediately after the if) that checks for cin.get() != '\n'. This will be true if there is extra data in the input, and you can provide an error message and add the ignore() line there to ignore the bad data.
• 11-02-2007
Molokai
Daved, that was exactly what I needed. It works absolutely perfect now! Here's the code:
Code:

```#include <cstdlib> #include <ctime> #include <iostream> #include <ctype.h> using namespace std; //returns value between 0 and RAND_MAX //rand(); //srand (time(0)); int x,w,random,guess,option,number,tries; int on = 1; char play; int game (){     do {         cout << "\nEnter a difficulty level: \n1. Easy\n2. Medium\n3. Hard\n4. Very Hard\n5. Insane!\n\n";//States possible difficulties         cin >> w;         if (w==1) x = 50;         if (w==2) x = 100;         if (w==3) x = 500;         if (w==4) x = 1000;         if (w==5) x = 10000;//Determines upper limit for random generator         srand(time(0));//Random seed         random = rand() % x + 1;//Random number generation         cout << "\nNumber chosen between 1 and " << x << ".\n";         cout << "Enter your guess.\n";         tries = 0;         while (guess != random){             if (!(cin >> guess) || (cin.get() != '\n')) {                 cin.clear(); // clear fail state                 cin.ignore(numeric_limits<int>::max(), '\n'); // ignore bad input                 cout << "\nIllegal guess.  Your guess must be a whole number.\n";                 --tries;             }             else if ((guess > x) || (guess < 1)) {                 cout << "\nIllegal guess.  Your guess must be between 1 and " << x << ".\n";//Keeps player from inputting a number that is not available                 --tries;//Sets counter back to keep track of legal guesses only             }                 else if (guess > random)                 cout << "\nYou guessed too high.\n";                 else                 cout << "\nYou guessed too low.\n";//The actual process of guessing the number                     cout << "Enter your guess.\n";                     ++tries;         }             cout << "\nYou Guessed It!\n";             cout << "You took " << tries << " guesses.\n";//Displays number of legal guesses required to win the round             cout << "Would you like to play again (Y/N)?\n";//Asks if player wants to play again, feeds into do...while loop parameter             cin >> play;     } while ((play == 'y') || (play == 'Y'));     return 0; } int menu(){     cout << "Main Menu: \n1. New Game \n2. Quit\n";     cin >> option;     if (option == 1)         game();     else         on = 0;     return 0; } int main(){     cout << "Welcome to Guess It, the number guessing game.\n";         do {         menu();     } while (on == 1);         return 0; }```
Anyone can feel free to compile it and run it if they like. However, now I'm faced with a completely new problem: the High Scores. Anyone?
• 11-02-2007
Daved
Do you want them saved over time, or just while the program is running and then have them reset the next time you start?

If you want them saved, you'll need to save them in a file, which means using ofstream and ifstream to read and write the scores. If you only want the top score or two, you'll need variables to remember them. If you want top five or ten or more, then you'll also want some sort of container like vector to remember the top scores.

You'll also need to read in strings to get the player's name.

So if you know about strings, fstreams or vectors already, then you can get started. Otherwise I'd take it slow. Perhaps start by keeping a variable that holds the high score for the current session and updating it as appropriate. Then maybe add a string variable to hold the user's name that has the high score. Then perhaps learn vector and how to hold multiple high scores. And then maybe save them out to a file. Each step along the way you'll have a new feature that enhances the game, but you'll be taking it slowly and not trying too much at a time.
• 11-02-2007
Molokai
Alright, so I suppose this isn't really a surprise, but when I was finally able to put this together on Visual C++, it came up with two errors where it compiled perfectly fine on Dev-C++. I also got the normal warning about possible data loss in converting from time_t (for seeding the random number). Anyway, here are the errors:
Code:

```1>.\GuessIt.cpp(33) : error C2065: 'numeric_limits' : undeclared identifier 1>.\GuessIt.cpp(33) : error C2062: type 'int' unexpected```
Here is the line it is referring to:
Code:

`cin.ignore(numeric_limits<int>::max(), '\n'); // ignore bad input`
And I have the following includes:
Code:

```#include <cstdlib> #include <ctime> #include <iostream> #include <ctype.h>```
Anyone know how to fix this? Are there additional include paths I need to put into VS that are already in Dev-C++?
• 11-02-2007
Daved
numeric_limits is found in <limits>.

Sometimes when you forget to #include the right header, some compiler's will still compile the code. You shouldn't rely on this behavior, though, so when you use something from a library you should look up which header it is in and make sure you include that.
• 11-02-2007
Molokai
Thanks, that did it. Guess I should either bookmark an include website or get a reference...

So, now I'm working on the basic high score, not saved. I'm trying to make it in an array, which I successfully declared, and I'm trying to have the array address of the high score determined by the difficulty level. So, here's what I tried (the red colored lines are the ones key to the high score):
Code:

```#include <stdafx.h> #include <cstdlib> #include <ctime> #include <iostream> #include <limits> using namespace std; //returns value between 0 and RAND_MAX //rand(); //srand (time(0)); int x,w,t,random,guess,option,number,tries; int on = 1; char play; int highscore[6]; int game (){     do {         cout << "\nEnter a difficulty level: \n1. Easy\n2. Medium\n3. Hard\n4. Very Hard\n5. Insane!\n\n";//States possible difficulties         cin >> w;         if (w==1) x = 50;         if (w==2) x = 100;         if (w==3) x = 500;         if (w==4) x = 1000;         if (w==5) x = 10000;//Determines upper limit for random generator         srand(time(0));//Random seed         random = rand() % x + 1;//Random number generation         if (highscore[w] == 0)             highscore[w] = x;         if ((highscore[w] != 0) && (highscore[w] < x))             cout << "\nCurrent high score: " << highscore[w];         cout << "\nNumber chosen between 1 and " << x << ".\n";         cout << "Enter your guess.\n";         tries = 0;         while (guess != random){             if (!(cin >> guess) || (cin.get() != '\n')) {                 cin.clear(); // clear fail state                 cin.ignore(numeric_limits<int>::max(), '\n'); // ignore bad input                 cout << "\nIllegal guess.  Your guess must be a whole number.\n";                 --tries;             }             else if ((guess > x) || (guess < 1)) {                 cout << "\nIllegal guess.  Your guess must be between 1 and " << x << ".\n";//Keeps player from inputting a number that is not available                 --tries;//Sets counter back to keep track of legal guesses only             }                 else if (guess > random)                 cout << "\nYou guessed too high.\n";                 else                 cout << "\nYou guessed too low.\n";//The actual process of guessing the number                     cout << "Enter your guess.\n";                     ++tries;         }             cout << "\nYou Guessed It!\n";             cout << "You took " << tries << " guesses.\n";//Displays number of legal guesses required to win the round         if (tries < highscore[w]){                 highscore[w] = tries;                 cout << "\nNew High Score!  New score: " << highscore[w] <<"!\n";         }             cout << "Would you like to play again (Y/N)?\n";//Asks if player wants to play again, feeds into do...while loop parameter             cin >> play;     } while ((play == 'y') || (play == 'Y'));     return 0; }```
Now, how can I apply this to displaying them, such as in a menu option? I don't want them to be close, but I don't want to have to put in a few dozen spaces to have them separated. I think I remember reading somewhere that there is a possible I/O stream command to make an output left-aligned or right-aligned. Would that work?
• 11-02-2007
Molokai
Oh, and does anyone know a good way to set the console prompt size in the code of the program right from the start?
Show 80 post(s) from this thread on one page
Page 1 of 2 12 Last