Programming Forums
User Name Password Register
 

RSS Feed
FORUM INDEX | TODAY'S POSTS | UNANSWERED THREADS | ADVANCED SEARCH

Reply
 
Thread Tools Display Modes
Old Dec 1st, 2007, 1:05 PM   #1
3n!
Newbie
 
Join Date: Dec 2007
Posts: 4
Rep Power: 0 3n! is on a distinguished road
Guess a Number

Yeah I know, it's a lame old game that beginner programmers make.

The book I'm working out of, "Beginning C++ through Game Programming" has a 'challenge' if you will at the end of Chapter 2. Instead of having the computer choose a random number and you guess, you have to choose the number and the computer guesses. I'm trying to figure out how to set up the random number generator to set its limits based on two variables.

What I'm trying to do is, guessLow = 1, guessHigh = 100. When the computer guesses a number, if its over my chosen number, it will assign the variable guessHigh with the computers guess, and loop back to the rand function, where it randomly chooses between guessLow and guessHigh again, eventually narrowing it down to my chosen number.

The problem I run into is with the rand function itself. How do I set it up to pick a number between two variables that already have numbers assigned to them?

I don't care about anything but getting this function to work.
Here is what I have so far, though obviously incomplete:

// Guess the Number
// The player chooses a number and the computer guesses what that number is.

#include "stdafx.h"
#include <iostream>
#include <ctime>
#include <cstdlib>

using namespace std;

int main()
{
	srand(time(0)); // seed the number generator with the time

	int guess;
	int guessLow = 1;
	int guessHigh = 100;
	int pNumber;
	
	cout << "Select a number between 1 and 100: ";
	cin >> pNumber;

	if (pNumber >= 101) // tell the player that if he chooses something above 100, he's wrong
		cout << "Please don't choose a number above 100, or while we're at it anything negative.";
	else
		cout << "Thank you, now the computer is going to guess your number.";


	/* The computer guesses between the lowest guess thus far, and the highest
	then based on whether its too high or too low, the number is assigned to the
	variables 'guessLow' and 'guessHigh'. Then the computer executes the same
	process a the top, resulting in it eventually being narrowed down to the
	player's number of choice.*/

	while (guess != pNumber)
	{
		int guess = rand(guessLow - guessHigh);
		cout << "\n\nComputers guess: " << guess << endl;
		
		if (guess < pNumber)
		{
			cout << "\nToo low, guess again.";
			guessLow = guess;
		}
	}
	return 0;
}

I know that "int guess = rand(guessLow - guessHigh);" is way out there, cause thats like Low minus High, what I'm looking for is the operator that says "through"

Last edited by 3n!; Dec 1st, 2007 at 1:07 PM. Reason: explanation
3n! is offline   Reply With Quote
Old Dec 1st, 2007, 1:26 PM   #2
Jimbo
Battle Programmer
 
Jimbo's Avatar
 
Join Date: Feb 2006
Location: Bellevue, WA, USA
Posts: 763
Rep Power: 3 Jimbo is on a distinguished road
Re: Guess a Number

for a simple solution, you could do something like this:
int guess = rand() % (guessHigh - guessLow); // this will get you within the value difference
guess += guessLow; // this will get you into your exact range
This will provide a decently random range [guessLow, guessHigh).
__________________
<insert disclaimer here>
<insert shameless plug for Visual Studio here>
Jimbo is online now   Reply With Quote
Old Dec 1st, 2007, 1:30 PM   #3
3n!
Newbie
 
Join Date: Dec 2007
Posts: 4
Rep Power: 0 3n! is on a distinguished road
Re: Guess a Number

So for instance, its 1-100, and my number is 50. The computer chooses 75. This will make it so next time it randomly chooses a number it will choose between 1 and 75?

Then for instance if it chooses 22 next, it will follow up again choosing between 22 and 75?

Thanks for the help.
3n! is offline   Reply With Quote
Old Dec 1st, 2007, 2:03 PM   #4
Jimbo
Battle Programmer
 
Jimbo's Avatar
 
Join Date: Feb 2006
Location: Bellevue, WA, USA
Posts: 763
Rep Power: 3 Jimbo is on a distinguished road
Re: Guess a Number

I changed your code a little bit to make sure mine was working like I thought. There were also a couple compiler warnings. Here's the new code (I only changed the loop):

cpp Syntax (Toggle Plain Text)
  1. // made this a do-while because you were using guess in the while
  2. // condition when it was still uninitialized. Since you have
  3. // to go through the loop at least once, this change is better
  4. // anyways.
  5. do
  6. {
  7. cout << "Guessing range is between " << guessLow << " and " << guessHigh << endl;
  8.  
  9. // I added the +1 so the range would be [guessLow, guessHigh]
  10. guess = rand() % (guessHigh - guessLow + 1); // this will get you within the value difference
  11. guess += guessLow; // this will get you into your exact range
  12.  
  13. cout << "Computer's guess is: " << guess << endl;
  14.  
  15. if (guess < pNumber)
  16. {
  17. cout << "Too low, guess again.\n";
  18. guessLow = guess;
  19. }
  20. // added this part
  21. else if (guess > pNumber)
  22. {
  23. cout << "To high, guess again.\n";
  24. guessHigh = guess;
  25. }
  26.  
  27. }
  28. while (guess != pNumber);
and here's the output to show how it works:
Select a number between 1 and 100: 35
Thank you, now the computer is going to guess your number.Guessing range is between 1 and 100
Computer's guess is: 32
Too low, guess again.
Guessing range is between 32 and 100
Computer's guess is: 93
To high, guess again.
Guessing range is between 32 and 93
Computer's guess is: 63
To high, guess again.
Guessing range is between 32 and 63
Computer's guess is: 49
To high, guess again.
Guessing range is between 32 and 49
Computer's guess is: 37
To high, guess again.
Guessing range is between 32 and 37
Computer's guess is: 33
Too low, guess again.
Guessing range is between 33 and 37
Computer's guess is: 35
__________________
<insert disclaimer here>
<insert shameless plug for Visual Studio here>
Jimbo is online now   Reply With Quote
Old Dec 1st, 2007, 2:12 PM   #5
3n!
Newbie
 
Join Date: Dec 2007
Posts: 4
Rep Power: 0 3n! is on a distinguished road
Re: Guess a Number

Beautiful!

Exactly what I was trying to do. So basically my mistakes were:
A) Using a while loop as apposed to a do/while loop and thats why I was getting the uninitialized 'guess' identifier error. Using a do/while loop places 'guess' at the bottom, avoiding that error.

B)The way I used the rand function. I had the concept down, just not the proper format.

Thank you much for the help. I much appreciate it.
3n! is offline   Reply With Quote
Old Dec 1st, 2007, 2:21 PM   #6
Jimbo
Battle Programmer
 
Jimbo's Avatar
 
Join Date: Feb 2006
Location: Bellevue, WA, USA
Posts: 763
Rep Power: 3 Jimbo is on a distinguished road
Re: Guess a Number

Quote:
Originally Posted by 3n! View Post
A) Using a while loop as apposed to a do/while loop and thats why I was getting the uninitialized 'guess' identifier error. Using a do/while loop places 'guess' at the bottom, avoiding that error.
That's the basic idea. You could also have done something like initializing guess when you declared it, e.g. int guess = 0; so that it would be initialized. I decided to use a do-while for 2 reasons: 1) you need to go through the loop at least once; and 2) the first thing done in the loop is to set the value of guess, so you know that its value won't be read until it's been properly assigned.

While I'm thinking about it... when you check that pNumber is 100 or less, you should also have a check that it's greater than 0. Just putting a message to the user (especially after the checks) is too late and too little. You should start a habit of always checking user input for any error conditions.
__________________
<insert disclaimer here>
<insert shameless plug for Visual Studio here>
Jimbo is online now   Reply With Quote
Old Dec 1st, 2007, 2:22 PM   #7
3n!
Newbie
 
Join Date: Dec 2007
Posts: 4
Rep Power: 0 3n! is on a distinguished road
Re: Guess a Number

I edited it a little bit to get rid of repeating numbers:
		if (guess < pNumber)
		{
			cout << "\nToo low, guess again.";
			guessLow = guess + 1;
		}

		else if (guess > pNumber)
		{
			cout << "\nToo high, guess again.";
			guessHigh = guess - 1;
		}

Though its rare, I'm OCD and had to get rid of them.

Thanks again for the help.
3n! is offline   Reply With Quote
Old Dec 2nd, 2007, 3:38 AM   #8
lectricpharaoh
Caffeinated Neural Net
 
lectricpharaoh's Avatar
 
Join Date: Jun 2005
Location: Dry west coast of Canada
Posts: 1,033
Rep Power: 5 lectricpharaoh will become famous soon enough
Re: Guess a Number

Glad to see you got it sorted. However, if you want a uniform (as much as possible, anyways) distribution of your random numbers, don't use modulus. To illustrate why, imagine I have a function that returns a number from one to ten, but I want a number from one to four, so I get the result mod four, plus one. Let's also assume I call it ten times, and get a unique result each time (thus, it returns a perfectly uniform distribution). I then do the modulus:
 1 % 4 + 1 = 2
 2 % 4 + 1 = 3
 3 % 4 + 1 = 4
 4 % 4 + 1 = 1
 5 % 4 + 1 = 2
 6 % 4 + 1 = 3
 7 % 4 + 1 = 4
 8 % 4 + 1 = 1
 9 % 4 + 1 = 2
10 % 4 + 1 = 3
As you can see, I get some results more frequently than others, and it's not because of a small set. It actually happens when the divisor for your modulus is not a factor of your initial range. There are numerous ways to remedy this (short of writing your own PRNG), but rather than try to explain, let me just refer you to Narue's excellent article on just this subject.

On another note, you should check for input validity. If the user enters "hello" instead of "54" for their guess, your program will die horribly. Use cin.good() or a similar method to ensure the input was successfully parsed and assigned to the variable, and then do range checking. I noticed you checked to see if the value was too high, but not if it was too low. You can combine both checks in the same expression:
if((pNumber < 1) || (pNumber > 100))
  // error, prompt for another number
Another solution is to use unsigned types, though in your case, you'd need to then make zero a valid choice (or keep both tests in the conditional). If you know all negative values are out of range, this option makes sense, provided you don't mix signed and unsignedarithmetic (weird things can happen if you're not careful).

Lastly, have you considered making the computer's algorithm 'smart'? You can use a divide-and-conquer approach similar to a binary search to get the number. Basically, you cut the range in half, and choose that number. When you determine the number is higher or lower, you know the new range (by excluding half of the previous range). Repeat until the correct number is found.
__________________
And once again, Probability proves itself willing to sneak into a back alley and service Drama as would a copper-piece harlot.
- Vaarsuvius, Order of the Stick
lectricpharaoh is online now   Reply With Quote
Reply

Bookmarks

« Previous Thread in Forum | Next Thread in Forum »

Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
c-unix-childprocesses-random number programmingnoob C 7 Feb 6th, 2007 8:39 PM
pointer number alteration Blighttdm C 5 Oct 14th, 2005 7:24 PM
Number Guessing Game Dark Flare Knight Java 15 Apr 4th, 2005 3:40 PM
non repeating random number generation gencor45 C# 2 Feb 9th, 2005 12:11 AM
Number Systems... Ade Coder's Corner Lounge 7 Jan 19th, 2005 5:32 AM




DaniWeb IT Discussion Community
All times are GMT -5. The time now is 11:08 PM.

Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC