Sign in to follow this  
actormike86

Creating New Guess My Number game

Recommended Posts

actormike86    100
I just picked up Beginning C++ through Game Programming and I've been understanding everything so far pretty well, having no prior language experience. Chapter 2 has the following exercise: Write a new version of the Guess My Number program in which the player and the computer switch roles. That is, the player picks a number and the computer must guess what it is. Here is what I have so far. // Guess My Number 2 // Computer attempts to guess my number #include <iostream> #include <cstdlib> #include <ctime> using namespace std; int main() { cout << "\tWelcome to Guess My Number\n\n"; cout << "\tCan the computer guess your number?\n\n"; int myNumber; cout << "Enter a number between 1-100: "; cin >> myNumber; srand(time(0)); int randomNumber = rand() % 100 + 1; int tries = 0; do { randomNumber = rand() % 100 + 1; cout << randomNumber << endl; ++tries; } while (randomNumber != myNumber); cout << "\nIt took the computer " << tries << " guesses!\n"; return 0; } This works really well but makes the computer work harder than it should. I mean this because I have the script set to make the computer guess ANY number allowing repeats as well as not guessing within the correct parameters. What I want it to do is if I choose 50 for the number and the computer guesses 51, I want to limit the computer to numbers below 51 because why would it choose over 51. Also, I don't want it to try to choose the same number. So far, it has take the computer anywhere between 100 and 400 guesses to get it right. Any suggestions would be helpful. Thanks. MH

Share this post


Link to post
Share on other sites
fastcall22    10845
The simplest algorithm would be to use a binary search. Otherwise, use the formula rand()%(max-min+1)+min to get a random number between min and max. From here, you just need to decide when to set min, and when to set max when the computer is guessing. Hope this helps!

Share this post


Link to post
Share on other sites
Your first question (how to keep the computer guessing within the correct range) is easy: Create two 'ints' and use them to store the highest and lowest possible numbers, that the computer knows is still possible. If the computer guesses 72, and that's too high, then set the 'highestPossible' int, to 72, and make the computer only guess numbers below that. If the computer guesses 12, and it's too low, the make the 'lowestPossible' int be 12, and make the computer only guess above that.
This way, you keep it within the range of 'highestPossible' and 'lowestPossible', and as the computer guesses, it'll keep on shrinking that range (like a human's guesses) until it finds the right number.

To make it guess within that range, we alter your random number generating, slightly.

First, we find the range between the two numbers.
int range = (highestPossible - lowestPossible);
Then we generate a number based off that range.
randomNumber = (rand() % range) + lowestPossible + 1;
Example:
int lowestPossible = 1;
int highestPossible = 100;

do
{
int range = (highestPossible - lowestPossible) + 1;

//We change our random number generator, to always generate a number between 'lowestPossible' and 'highestPossible'.
randomNumber = rand() % range + lowestPossible;

cout << randomNumber << endl;

//If the computer's guess is lower then the player's chosen number...
if(randomNumber < myNumber)
{
//...then the computer now knows it's too low, so we set 'lowestPossible' to the computer's guess.
//(He'll always guess higher than 'lowestPossible' from now on)
lowestPossible = randomNumber;
}
//If the computer's guess is higher then the player's chosen number...
if(randomNumber > myNumber)
{
//...then the computer now knows it's too high, so we set 'highestPossible' to the computer's guess.
//(He'll always guess lower than 'highestPossible' from now on)
highestPossible = randomNumber;
}

++tries;
} while (randomNumber != myNumber);



Your second question (have the computer not guess the same question twice) is also pretty easy, but it requires introducing you to some programming concepts may seem confusing to you, since you'll be introduced to them ealier than you should be.



To make the computer not guess the same number twice, create a container and fill it with every possible guess (1 - 100 in your case), then each time the computer guesses a number, remove it from the container.

We'll use std::list as our container. (You'll need to '#include' the '<list>' header)

You probably haven't used std::list before, so it'll look wierd to you, but it's the easiest way to do what you want.

A std::list is, sort of, a variable like 'int' or 'bool'. To declare a new std::list, we go like this:
std::list <int> myList;
You don't have to type 'std::' if you don't want to, since you have 'using namespace std' in your program.

This creates a list, and the variable between the < > brackets, tells us what kind of list it is. In our case, we want a list of numbers (the numbers the computer hasn't yet guessed) so we make it a list of <int>.

To fill the list up with 100 numbers, from 1 to 100, we can use a for() loop.
If you call myList.push_back( myNumber ) you can add a number to the list. We want to do this 100 times, so we use the for() loop to loop 100 times.
for(int i = 1; i <= 100; i++)
{
unguessedNumbers.push_back(i); //Adds the number contained in 'i' to the list.
}
We only need to do this once per match/game/whatever.

Now, instead of getting a random number between 'lowestPossible' and 'highestPossible', we get a random number between 0 and the size of the container holding our numbers. This random number is no longer the number the computer is guessing - instead, it's the location (also known as an 'index') in the container, that holds the computer's guess (remember that the container holds every number between 1 and 100 that wasn't already guessed).
int index = rand() % (unguessedNumbers.size() + 1);

We then get what's called an 'iterator' (also a type of variable), and increment it by the index, to access the location in the container that holds the number (the computer's guess) we want.
//Get the start/beginning of the container.
std::list<int>::iterator iterator = unguessedNumbers.begin();

//Keep incremending the 'iterator', until we increment it to the location we want.
for(int i = 0; i < index; i++)
iterator++;

//Get the guess out of the container.
computerGuess = (*iterator);

//Erase that number/guess from the container, so it can't be re-guessed.
unguessedNumbers.erase(iterator);


Then we check if the computer's guess is within the range we want (lowestPossible and highestPossible), and if it's not, we go get another number from the container, until we find one that is within range. (Since we already removed each number we get out of the container, the container will hold less and less numbers, and sooner or later we'll reach one that's within range)



Confused? Don't be afraid to ask questions.

Read the comments in the code below, and alter the code as much as you like, to see what you can understand and what you can't. If something looks really really wierd (like std::list and std::list<int>::iterator) then either ask questions, or else don't worry about it, you'll learn about them later; you've just been introduced to them earlier than you should have (do to the nature of your question).
#include <iostream>
#include <ctime>
#include <list>

using namespace std;

int main()
{
std::list <int> unguessedNumbers;

srand(time(NULL));

std::cout << "\tWelcome to Guess My Number\n\n";
std::cout << "\tCan the computer guess your number?\n";

bool quit = false;

//We loop until the player is ready to quit.
while(quit == false)
{
for(int i = 1; i <= 100; i++)
{
unguessedNumbers.push_back(i); //Adds the number contained in 'i' to the list.
}

int highestPossible = 100;
int lowestPossible = 1;

int myNumber;
std::cout << "\nEnter a number between 1-100: ";
std::cin >> myNumber;

int tries = 0;

bool stillGuessing = true;

//We keep looping, until the
while(stillGuessing == true)
{
int computerGuess = 0;

std::cout << "Guess: ";

bool foundAGoodGuess = false;

//We keep looping, getting new guesses, until we find a guess that's within the correct range.
while(foundAGoodGuess == false)
{
int index = rand() % unguessedNumbers.size() + 1;

//Get the start/beginning of the container.
std::list<int>::iterator iterator = unguessedNumbers.begin();

//Keep incremending the 'iterator', until we increment it to the location we want.
for(int i = 0; i < index; i++)
iterator++;

//Get the guess out of the container.
computerGuess = (*iterator);

//Erase that number/guess from the container, so it can't be re-guessed.
unguessedNumbers.erase(iterator);

//Check if the guess is within the range we want. (The && symbol means 'and'. We are checking if
//the computer's guess is greater than the lowest possible, AND if it's less than the highest possible)
if(computerGuess > lowestPossible && computerGuess < highestPossible)
{
//If we found a guess within the correct range, we can end this loop.
foundAGoodGuess = true;
}
}

std::cout << "\nThe computer guessed " << computerGuess << "! ";

tries++;

//If the computer guesses too low, we set 'lowestPossible' to that guess, so the computer wont ever guess lower than that again.
if(computerGuess < myNumber)
{
std::cout << "Too low...\n";
lowestPossible = computerGuess;
}
//If the computer guesses too high, we set 'highestPossible' to that guess, so the computer wont ever guess higher than that again.
else if(computerGuess > myNumber)
{
std::cout << "Too high...\n";
highestPossible = computerGuess;
}
//If the computer guesses correctly, then we set 'stillGuessing' to false, since the computer is done.
//Now, we can start again, and choose a new number for it to guess.
else if(computerGuess == myNumber)
{
std::cout << "That's correct.\n";
std::cout << "It took the computer " << tries << " guesses!\n";
stillGuessing = false;
}
}

std::cout << "\nDo you want to play again? yes/no";
std::string answer;
std::cin >> answer;

//The '!=' symbol means 'not equal to'. It's the opposite of the '==' symbol.
if(answer != "yes" && answer != "y")
{
quit = true;
}
}

return 0;
}


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