Sign in to follow this  
Poro

Problem with a number guessing game

Recommended Posts

Hello! So now that I have had the enumerator problem solved, I have another problem. I tried to make a number guessing game, where the computer tries to guess the number that player chooses. It just seems that computer never guesses it. I think I have seen it guessing the right number, but the game does not finish. Here is the code:
#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;

int main()
{
    int number;
    
    
    cout << "Welcome to number guessing game. In this game, you will make up a number ";
    cout << "and the computer will try to guess it. Pick a number between 1-100\n" ;
    do
    {
    cout << "\nYour number: ";
    cin  >> number;
    if ( 1> number || number >100 )
       cout << "Your must be between 1-100!";
} while ( 100< number || number <1   );
    
    int tries = 0, compGuess;
   
         
    do
    {
          srand(time(0));
         int compGuess = rand () % 100 +1;
         cout << "\nComputer guesses: " << compGuess << endl;
         ++tries;
         
         if (compGuess > number)
            cout << "Computer guessed too high!\n";
            
         if (compGuess < number)
            cout << "Computer guessed too low!\n";
} while ( compGuess != number);

cout << "\nComputer got your number right! It took " << tries << " guesses! \n";
system("pause");

return 0;
} 

Share this post


Link to post
Share on other sites
You enter a number b/w 1 & 100
Computer randomly guesses a number between 1 & 100
If it is wrong, it randomly guessess a new number b/w 1&100.

Think about it - that chances of guess correct are 1 in 100 (roughly). So very low. That is probably why you never see it guess correctly, even though it can do many, many iterations. I'm not sure about how well distributed rand() is, so it might infrequently be genereating a certain set of numbers, making it less likely to guess your answer

If you change it to 'tweak' its guess based on if it is too low or too high, then you'll see it quickly guess your number.

Share this post


Link to post
Share on other sites
I don't think that's the answer I tried it and it can choose the right number but never exits the loop. For example, try changing the range it guesses from 1-2 and choose that as your number, even when it picks the right number it's not breaking the loop. It's not obvious as to why either, because if I print out the two right before the end of the loop it says they are the same, but it won't break the loop.

if you add :
if (compGuess==number)
{
cout <<"equal guess \n";
break;
}

it works.

Also, you don't need to seed the random number generator on every loop, I actually think that makes it less likely to be random since on some occasions the time(0) returns the same value, causing it to pick the same number multiple times.

Share this post


Link to post
Share on other sites
Your problem is that you create the variable compGuess twice. First you make it outside the guessing loop, where you should, with this line:
int tries = 0, compGuess;
Then you make it inside the loop with this line:
int compGuess = rand() % 100 +1;
You store the guess in the one inside the loop, which is destroyed before
while ( compGuess != number);
is evaluated, so that line references the one you made outside the loop, which is never changed. Your program should work much better if you just change
int compGuess = rand() % 100 +1;
to
compGuess = rand() % 100 +1;

Share this post


Link to post
Share on other sites
Hmmm yeah, just tried playing with it. If you don't reseed every iteration and add an
 		if(compGuess == number)
break;
it then works like a charm...I have no idea why that isn't being caught in the while condition though...

Quote:
Your problem is that you create the variable compGuess twice.

omg, I can't believe I missed that. But yes, that is definitely the answer

Share this post


Link to post
Share on other sites
Got it working now, after I removed the int from int compGuess = rand () % 100 +1;. I also moved the random number generator seed outside from the loop, as you suggested , and now the computer gets the number with far less tries. Thanks!

Share this post


Link to post
Share on other sites
OK, so you've got "something working", but I think you've missed the point of the exercise. Don't feel bad; almost everyone seems to end up with something like this.

But think about it: when you guess the computer's number, do you know what it is? No? So, the computer shouldn't know the number when it's guessing, either. Instead, you pick the number. It's not a variable stored in the program, just like the computer's random number selection isn't a "variable" stored in your brain when you're doing the guessing.

Now, how do you make your decisions for guessing? Based off of what the computer tells you (too high/too low), yes? So, if you want the computer to play "properly", then you need to be able to tell it if its guess is too high or too low. That is, each time the computer guesses, it will prompt for input, and you type in whether it's too high or too low. The program has to read the response, interpret it (potentially the tricky part - depending on exactly what you're willing to accept as a "valid" response from the user), and make its next guess.

Finally, how exactly do you make your decision, once you've been told "too high" or "too low"? If it's too high, you guess something lower; if it's too low, you guess something higher. But you also respect any previous information you got. Basically, at the start, you know a minimum and maximum possible value for the number, and you guess something in between. Based on what you're told, you can revise either your minimum or your maximum, and then guess something in that range. So, try programming in that logic.

Share this post


Link to post
Share on other sites
Good point, Zahlman. I decided to fix the things you told in your post, and also decided to extend my number game a little bit. I encoutered many problems that I can't understand.

First, I can't understand why the computer replaces my while loop with a smilie? Also, it exits the loop even when input is invalid or N, but I am not sure if that is related to the smilie thing. http://www.imagebam.com/image/a1dabc3489194
while(true)
{
cout << "\nAre you ready? Y for yes and N for no: ";
cin >> ready;

if(ready = 'y' || 'Y')
{
cout << ready << endl;
break;
}

if(ready = 'n' || 'N')
{
cout << ready << endl;
continue;
}

if(ready != 'n' || 'N' || 'y' || 'Y' )
{
cout << "Invalid answer!" << endl;
}
}





Then I have problem with my Do loop. It exits from the loop even when it should not. For example, I press L and it exits the loop, even though there is no Break; command and the loop condition is set to True.

do
{
cout << "Did the computer guess your number? H for too high, ";
cout << "R for right number, and L" << endl << "for too low." << endl;
cin >> answer;

if(answer = 'r' || 'R' )
break;
if(answer = 'l' || 'L')
{
compGuess = rand() % compGuess +1;
cout << "Computer guessed: " << compGuess << endl;
tries++;
continue;
}
if(answer = 'h' || 'H')
{
compGuess = rand () % compGuess +50;
cout << "Computer guessed: " << compGuess << endl;
tries++;
continue;
}
} while(true);





Then I have a problem with mathematics. I think I have the low part working correctly, so that the computer guesses lower if user says the number is lower, but I am not quite sure about the higher one. So how would I get the computer guessing higher number than the previous, but still under 100? I am currently using
compGuess = rand () % compGuess +51;


, but I very much think that won't work.

Here is the whole code:
#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;

int main()
{
int number;
char ready;

cout << "Welcome to number guessing game. In this game, you will make up a number ";
cout << "and thecomputer will try to guess it. Think about a number between 1-100\n";

while(true)
{
cout << "\nAre you ready? Y for yes and N for no: ";
cin >> ready;

if(ready = 'y' || 'Y')
{
cout << ready << endl;
break;
}

if(ready = 'n' || 'N')
{
cout << ready << endl;
continue;
}

if(ready != 'n' || 'N' || 'y' || 'Y' )
{
cout << "Invalid answer!" << endl;
}
}

int tries = 0, compGuess;
srand(time(0));
char answer = 'h';

compGuess = rand () % 100 +1;
cout << "\nComputer guesses: " << compGuess << endl;
++tries;

do
{
cout << "Did the computer guess your number? H for too high, ";
cout << "R for right number, and L" << endl << "for too low." << endl;
cin >> answer;

if(answer = 'r' || 'R' )
break;
if(answer = 'l' || 'L')
{
compGuess = rand() % compGuess +1;
cout << "Computer guessed: " << compGuess << endl;
tries++;
continue;
}
if(answer = 'h' || 'H')
{
compGuess = rand () % compGuess +50;
cout << "Computer guessed: " << compGuess << endl;
tries++;
continue;
}
} while(true);

if(tries != 1)
cout << "Computer guessed your number with " << tries << "guesses!" << endl;
else
cout << "Computer guessed your number with his first guess!" << endl;

system("pause");
return 0;
}





Thanks in advance!

Share this post


Link to post
Share on other sites
Quote:
Original post by Poro
Good point, Zahlman. I decided to fix the things you told in your post, and also decided to extend my number game a little bit. I encoutered many problems that I can't understand.

First, I can't understand why the computer replaces my while loop with a smilie? Also, it exits the loop even when input is invalid or N, but I am not sure if that is related to the smilie thing. http://www.imagebam.com/image/a1dabc3489194
*** Source Snippet Removed ***

Then I have problem with my Do loop. It exits from the loop even when it should not. For example, I press L and it exits the loop, even though there is no Break; command and the loop condition is set to True.

*** Source Snippet Removed ***

Then I have a problem with mathematics. I think I have the low part working correctly, so that the computer guesses lower if user says the number is lower, but I am not quite sure about the higher one. So how would I get the computer guessing higher number than the previous, but still under 100? I am currently using *** Source Snippet Removed ***, but I very much think that won't work.

Here is the whole code:
*** Source Snippet Removed ***

Thanks in advance!


I have no idea what you mean by 'replaces my while loop with a smilie' so can't help you there.

Most of your other problems are because conditionals don't work like they do in english and that's throwing you off. In real life you can say "I don't want to go to the store, the park, or the school" but in C++ you need to say something more like "i dont' want to go to the store or I don't want to go to the park or I don't want to to go the school". So the first if statement in your post

if(ready = 'y' || 'Y')

should really be

if(read == 'y' || ready == 'Y')

Note you also used the 'assignment operator' instead of the 'equality operator'. That is '=' doesn't compare two things against each other it copies the right-handed thing to the left-handed thing. To make it more confusing, due to operator precedence the first part of your if statement to 'run' is just

'y' || 'Y' which is a boolean comparison. 'y' and 'Y' are converted to boolean values (true in this case), then ||'ed with each other. true || true is true. Next ready is assigned true. I recommend revisiting the section on operator precedence in your chosen reference source.

Most of your problems given should be as a result of your confusion. Fix those conditionals and it should work, if not 'fine' at least 'better'. Hope this helps.

Share this post


Link to post
Share on other sites
one thing you could do(however this could be horribly inefficient) is add each number to a vector, shuffle the vector, than use an interator to go through the vector and check each iteration to be equal to the user's number.

I did a guessing game same way as you, cept it was between 1-10.

To your current code, makesure you do use the == inside the if statements or any other comparison. Also where you have the:

if(answer = 'h' || 'H')


Replace with:

if(answer == 'h' || answer == 'H')


I know in java, one needs the left variable after an or/and statement. I've always done it that way, so maybe yours works fine in c++.


Also, why are you using while(true)? That will just create an infinite loop. You'll want to rework them as do loops with a proper while condition, much like this:

do
{
cout << "\nAre you ready? Y for yes and N for no: ";
cin >> ready;

if(ready = 'y' || 'Y')
{
cout << ready << endl;
break;
}

if(ready = 'n' || 'N')
{
cout << ready << endl;
continue;
}

if(ready != 'n' || 'N' || 'y' || 'Y' )
{
cout << "Invalid answer!" << endl;
}
}while (ready != 'y' || ready != 'Y');




Share this post


Link to post
Share on other sites
Thanks! I got most things sorted out! By the smilie thing I meant this: http://www.imagebam.com/image/a1dabc3489194

As you see, my while loop is gone and there is a smilie. I just can't understand where it came from, or how can I make those, but it is not an issue anymore. Your suggestions fixed it.

I still have one problem though. I can't make the program guess higher than the previous guess. How would I do that?

First guess: compGuess = rand () % 100 +1;
Guess, if the guess is too high: compGuess = rand() % compGuess +1;
If the guess is too low: How can I do this?

agm_ultimatex, I have no idea how to use vectors. :/

Share this post


Link to post
Share on other sites
Quote:
Original post by Poro
Thanks! I got most things sorted out! By the smilie thing I meant this: http://www.imagebam.com/image/a1dabc3489194

As you see, my while loop is gone and there is a smilie. I just can't understand where it came from, or how can I make those, but it is not an issue anymore. Your suggestions fixed it.

I still have one problem though. I can't make the program guess higher than the previous guess. How would I do that?

First guess: compGuess = rand () % 100 +1;
Guess, if the guess is too high: compGuess = rand() % compGuess +1;
If the guess is too low: How can I do this?

agm_ultimatex, I have no idea how to use vectors. :/


It's pretty simple stuff. But for 100 elements, it might be too inefficient to not be really worth it. Reread my post too, i added a bunch of info to it.

Share this post


Link to post
Share on other sites
I read your post and fixed the infinite loop, but I thought it shouldn't matter as I had break; there?

However, I still need an answer for my question.
Quote:
I still have one problem though. I can't make the program guess higher than the previous guess. How would I do that?

First guess: compGuess = rand () % 100 +1;
Guess, if the guess is too high: compGuess = rand() % compGuess +1;
If the guess is too low: How can I do this?

Share this post


Link to post
Share on other sites
Quote:
Original post by Poro
First guess: compGuess = rand () % 100 +1;
Guess, if the guess is too high: compGuess = rand() % compGuess +1;
If the guess is too low: How can I do this?


This is what I do when I need a random value in a range that doesn't begin at zero:

rand()%(MaxValue - MinValue) + MinValue;



In this case, your MinValue is the previous guess.

This is entirely off the top of my head, but that's the general idea. Find the range with a lower limit of zero, get the random number inside that range, and add the desired minimum value to move the lower limit up.

Share this post


Link to post
Share on other sites
Quote:
Original post by Poro
I read your post and fixed the infinite loop, but I thought it shouldn't matter as I had break; there?


It wouldn't have mattered. In general, we prefer to set a "natural" condition for ending a loop, and let it get checked automatically each iteration. But it also works to break out of an infinite loop, as long as you can be sure it will happen eventually. :)

Quote:
I still have one problem though. I can't make the program guess higher than the previous guess. How would I do that?

First guess: compGuess = rand () % 100 +1;
Guess, if the guess is too high: compGuess = rand() % compGuess +1;
If the guess is too low: How can I do this?


Recall the hint:

Quote:

Basically, at the start, you know a minimum and maximum possible value for the number, and you guess something in between. Based on what you're told, you can revise either your minimum or your maximum, and then guess something in that range.


You'll need to remember both a minimum and maximum value. First, figure out how to initialize them. Then figure out how to generate a random number in that range (redattack34 has the right idea).

Share this post


Link to post
Share on other sites
Quote:
Original post by redattack34
Quote:
Original post by Poro
First guess: compGuess = rand () % 100 +1;
Guess, if the guess is too high: compGuess = rand() % compGuess +1;
If the guess is too low: How can I do this?


This is what I do when I need a random value in a range that doesn't begin at zero:
*** Source Snippet Removed ***

In this case, your MinValue is the previous guess.

This is entirely off the top of my head, but that's the general idea. Find the range with a lower limit of zero, get the random number inside that range, and add the desired minimum value to move the lower limit up.


That would be your best option.

The way i was thinking was this generally:


#include <vector>
...

vector<int> numbers;
numbers.reserve(100);
for(i = 0; i < 100; i++)
{
numbers.push_back(i); //adds all the numbers to the vector.
}

random_shuffle(number.begin(), numbers.end());

bool compGuesses = true;
int tracker = 0;
do
{
cout << "Computer's guess: " << numbers[tracker] << endl;
tracker++;
cout << "Did the computer guess your number? H for too high, ";
cout << "R for right number, and L" << endl << "for too low." << endl;
cin >> answer;

if(answer = 'r' || 'R' )
{
compGuesses = false;
}
if(answer = 'l' || 'L')
{
compGuess = rand() % compGuess +1;
cout << "Computer guessed: " << compGuess << endl;
tries++;
}
if(answer = 'h' || 'H')
{
compGuess = rand () % compGuess +50;
cout << "Computer guessed: " << compGuess << endl;
tries++;

}

}while(compGuesses);



I'm no pro, quite the beginner in fact. I haven't tried the above, so I don't know if it will work or not. Try the other suggestions first.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this