Title: A "guess the number" game
Description: problem with random numbers
Hippocrass - January 12, 2006 12:09 AM (GMT)
As the "guess the number" game seems to be a common begginner's exercise, I decided to try my hand at it. This is my first "real" program, ie. I didn't just copy the source out of a book or tutorial. Of course, much of it is based on other sources only modified. The basic structure is modled on a hevily modified version of
this game by AJ Young.
My problem is, once you guess the random number once, and then opt to play again, a new random number is not generated. It just keeps reqireing the same number over and over again.
This seems to be the only problem so far that I cannot figure out.
| CODE |
// Guess the Number v1.00 // written jan/10/06 J. Harmon #include <stdio.h> #include <iostream> #include <cstdlib> #include <ctime> #include <string> using namespace std;
int highest = 10;
void Game() { int guess; // Generate a random number srand((unsigned)time(0)); int randNum; int lowest = 1; int range = (highest - lowest) + 1; randNum = lowest + int(range * rand() / (RAND_MAX + 1.0)); do { cout << "Please enter your guess: "; cin >> guess; // first check if the guess is within the allowed limits if((guess > highest) || (guess < 1)) { cout << "Silly! Your guess must be from 1 to " << highest << ".\n\n"; } if (guess > randNum) // guess is too high { cout << "Too high.\n\n"; } if (guess < randNum) // guess is too low { cout << "Too low.\n\n"; } }while(guess != randNum); // loops untill correct number is guessed cout << "Drat! You guesed it!\n\n"; }
int main() { string name; cout << "Please enter your name: "; cin >> name; cout << "Hello, " << name << ".\nI am thinking of a " << "number between 1 and " << highest << ".\nI bet " << "you can't guess what it is." << endl; Game(); // ask to play again. string answer; cout << "Would you like to play again?\nyes or no\n"; cin >> answer; // first check if the user ansewerd "yes" or "no" while((answer != "yes") && (answer != "no")) { cout << "Invalid response. Please answer yes or no.\n"; cin >> answer; } while(answer != "no") { Game(); cout << "Would you like to play again?\nyes or no\n"; cin >> answer; while((answer != "yes") && (answer != "no")) { cout << "Invalid response. Please answer yes or no.\n"; cin >> answer; } } cout << "Press enter to exit"; cin.get(); } |
AquaFox - January 16, 2006 07:07 PM (GMT)
xdracox - January 16, 2006 07:09 PM (GMT)
Neken - January 16, 2006 07:13 PM (GMT)
this is EXACTLY the same thing :P
AquaFox - January 16, 2006 07:48 PM (GMT)
I was gonna say that. There is no difference between NULL or 0. You should know that..
myork - January 16, 2006 07:52 PM (GMT)
A replacement for rand() and srand()
| CODE |
RANDOM(3) Linux Programmer's Manual RANDOM(3)
NAME random, srandom, initstate, setstate - random number generator.
SYNOPSIS #include <stdlib.h>
long int random(void); void srandom(unsigned int seed); |
This routines generate a better random number (ie the lower bits of the generated number are as random as the highre bits unlike rand()).
myork - January 17, 2006 03:57 AM (GMT)
| QUOTE (AquaFox @ Jan 16 2006, 02:48 PM) |
I was gonna say that. There is no difference between NULL or 0. You should know that..
|
True. For now.
But that does not make it good programmng to use 0.
NULL is a special value that has a special intrinsic meaning that provides information.
By using zero you are robbing anybody reading the code of that intrinsic meaning.
AquaFox - January 17, 2006 09:07 AM (GMT)
Intrinsic?
*AquaFox bows to teh wise one.
Hippocrass - January 17, 2006 11:10 PM (GMT)
| QUOTE (myork @ Jan 16 2006, 07:52 PM) |
A replacement for rand() and srand()
| CODE | RANDOM(3) Linux Programmer's Manual RANDOM(3)
NAME random, srandom, initstate, setstate - random number generator.
SYNOPSIS #include <stdlib.h>
long int random(void); void srandom(unsigned int seed); |
This routines generate a better random number (ie the lower bits of the generated number are as random as the highre bits unlike rand()).
|
How do I use this?
I have tried google, and get a lot of old C stuff which is largely unintelligible to me.UPDATE:Actually, I found the answer. the issue has been resolved.
Thank you for your help everyone.
ps.
I figured it out
here
myork - January 18, 2006 02:25 AM (GMT)
Unfortunately the article is bad.
If the difference between HI and LOW is small than rand is not a very good random number generator espesially if you use the modulus operator '%'
The newer version of rand solves all the problems of rand.
Just replace:
rand with random
srand with srandom
Now things should be OK.
FrozenKnight - January 18, 2006 11:40 AM (GMT)
i dont know if anyone is intrested but i wrote a random number generator using the Mersenne Twister algrothim (at least as well as i can understand it) there seems to be a problem with it generating extreamly low numbers at least for the first few uses (probably becasuse i seeded it with the ms random algrothim) but after that it runs fine. generating numbers that match my statistical annalsis within a reasonable margin.
i placed it in a windows DLL for anyone who wants to try it.
(yes myork i coded it in asm, which is why i didn't place the source here)
anyway for those who want to try it
Download HereYes it's only 1.19kb ziped and 4.00kb unziped (nearly imposiable for C or C++ which is why i used ASM for it) it can generate over 20 million random mumbers per sec on my 1.8 ghz comp.
The functions included are
sRand -Seeds the linar random function with the GetTickCount Api
Rand - Basicaly a copy of the Visual C++ linar random number generator
MTInit - seeds the Mersenne Twister algro with values from Rand (this is automaticaly called when the dll is initlized)
MTRand - Returns a 32bit random number
r4d6m1 - call this with a 32 bit int (only the last 16 bits are used though) to simulate rolling 4 dice and droping the lowest value.
myork - January 18, 2006 02:45 PM (GMT)
| QUOTE (FrozenKnight @ Jan 18 2006, 06:40 AM) |
| (yes myork i coded it in asm, which is why i didn't place the source here) |
This is probably one of those situations were assembly is the correct (or should I say probably better than C++) language to use. (assuming you added comments :-)
myork - January 18, 2006 02:47 PM (GMT)
If you want truly random numbers (rather than sudo-random)
Then check this out.
http://www.random.org/He/She is producing random numbers based on atmosheric noise.
FrozenKnight - January 19, 2006 10:47 AM (GMT)
| QUOTE |
| This is probably one of those situations were assembly is the correct (or should I say probably better than C++) language to use. (assuming you added comments :-) |
I wish i had commeted it better. i barely understood enough of the code C i was reading to implement the algrothim myself. And i dont think i could have done a better job with C or C++ because the algrothim was in persuedocode (think that is how you spell that) if someone needs help with it then i will send them the code and walk them through step by step.
this was a nightmare to implement becasue it though there are sevral sources on the net most of them are poorly documented and are hard to follow. the easiest to understand was at the same time the hardest to follow. i had to break the whole thing down into sections and follow the math instruction by instruction untill i finally got it working.
dr voodoo - January 19, 2006 03:44 PM (GMT)
| QUOTE (myork @ Jan 17 2006, 03:57 AM) |
| QUOTE (AquaFox @ Jan 16 2006, 02:48 PM) | I was gonna say that. There is no difference between NULL or 0. You should know that..
|
True. For now.
|
... and every futur standard that tries to be backward compatible. Also it is very likly that futur standards will use a different name for a keyword.
| QUOTE |
| But that does not make it good programmng to use 0. |
I wouldn't define good programming so stricktly and I'm not the only one
http://public.research.att.com/~bs/bs_faq2.html#null.
| QUOTE |
| NULL is a special value that has a special intrinsic meaning that provides information. |
No, actually it doesn't. If the value of 0 or NULL is interpreted as a pointer or as an integer depends alone on the context. Meaning that you only repeat information already contained in the interfaces (which doesn't have to be a bad thing but it's not additional information). As the compiler doesn't (have to) check for consitency of this information you can not assume that it is used correctly and therefore you can not assume that 0 is an integer or that NULL is a pointer. In fact the only compiler I know that checks this and issues warnings is the GCC.
myork - January 19, 2006 04:13 PM (GMT)
| QUOTE (dr voodoo @ Jan 19 2006, 10:44 AM) |
| QUOTE (myork @ Jan 17 2006, 03:57 AM) | | QUOTE (AquaFox @ Jan 16 2006, 02:48 PM) | I was gonna say that. There is no difference between NULL or 0. You should know that..
|
True. For now.
|
... and every futur standard that tries to be backward compatible.
|
Yes. But even between C/C++ there are suttle differences. (That normally don't affect anything but you should be aware of them).
Who is the StrawTroup guy? Makes no sense. :-)
| QUOTE (dr voodoo @ Jan 19 2006, 10:44 AM) |
| QUOTE | | NULL is a special value that has a special intrinsic meaning that provides information. |
No, actually it doesn't. If the value of 0 or NULL <snip>
|
The intrinsic meaning is that it points to an invalid address. Assigning 0 (or comparing) does not convey the same symantic information (unless you know that 0 is an invalid address [or are a compiler]). And though I (and you and a lot of people) do know this, when I read sombody else's code I do not assume that they know. So when I see sombody assigning 0 to a pointer I have to check their code more thouraly to verify that they are doing what they think they are doing.
So basically my objection boils down to:
I hate to do more work than I have too.
When I read other peoples code I assume they are not as good as me and anything funky needs to be checked carefully.
Using 0 as a pointer is one of those beginner mistakes that happens. So needs to be checked.
So when people use 0 on pointers it causes me more work. So by definition it must be bad. Anything bad is bad programming. Anybody doing bad programming is a bad programmmer. All bad programmers should be shot. Thus be Darwinism we will reach a steady state of a small pool of skilled Engineers. Because the pool is small we should be highly paid Engeneers (Sounds good to me).
C-Man - January 19, 2006 05:21 PM (GMT)
Well stroustrup write sin his book to use 0 instead of NULL , and that makes him a bad programmer ?
myork - January 19, 2006 08:45 PM (GMT)
Just because you are a genious at designing languages.
Does not make you a good programmer :-)
dr voodoo - January 19, 2006 08:47 PM (GMT)
| QUOTE (myork @ Jan 19 2006, 04:13 PM) |
| When I read other peoples code I assume they are not as good as me and anything funky needs to be checked carefully. |
What makes you assume that your code is consitent in this matter? The only way to assure this is to have the compiler check this. As long as this isn't given it doesn't make sence to make a difference between 0 and NULL as you can never be sure that the repeated information is correct.
| QUOTE |
| Using 0 as a pointer is one of those beginner mistakes that happens. So needs to be checked. |
Why is it an error? Perhaps an error in the design of the language but not in it's use.
| QUOTE |
| I hate to do more work than I have too. |
Me too and therefore I simply lookup the function or variable declaration. You have to do that anyway as you can't be sure that the 0/NULL information is correct. Makeing 0/NULL afterwards consitent is extra work.
You could now probably construct an example where you mix pointers and offsets and the meaning of 0 is not obvious by looking at the variable declarations. In this situation I agree that this repeated information would be useful but this also one of the cases where it's the most likly to go wrong by accident.
To put it short:
You cannot enforce the correct use of 0 or NULL by techincal means which makes the repeated information they provide unrelyable and therefore useless.
myork - January 19, 2006 11:01 PM (GMT)
| QUOTE (dr voodoo @ Jan 19 2006, 03:47 PM) |
| QUOTE (myork @ Jan 19 2006, 04:13 PM) | | When I read other peoples code I assume they are not as good as me and anything funky needs to be checked carefully. |
What makes you assume that your code is consitent in this matter? The only way to assure this is to have the compiler check this. As long as this isn't given it doesn't make sence to make a difference between 0 and NULL as you can never be sure that the repeated information is correct.
| QUOTE | | Using 0 as a pointer is one of those beginner mistakes that happens. So needs to be checked. |
Why is it an error? Perhaps an error in the design of the language but not in it's use.
| QUOTE | | I hate to do more work than I have too. |
Me too and therefore I simply lookup the function or variable declaration. You have to do that anyway as you can't be sure that the 0/NULL information is correct. Makeing 0/NULL afterwards consitent is extra work.
You could now probably construct an example where you mix pointers and offsets and the meaning of 0 is not obvious by looking at the variable declarations. In this situation I agree that this repeated information would be useful but this also one of the cases where it's the most likly to go wrong by accident.
To put it short: You cannot enforce the correct use of 0 or NULL by techincal means which makes the repeated information they provide unrelyable and therefore useless.
|
I could not understand the logic in any of those arguments can you explain!
FrozenKnight - January 20, 2006 08:35 AM (GMT)
Using 0 For Null is a practice that is only looked upon as good in assembly. the reason for that is that when you work with assembly you know the exact artecture you are working with. of cource assembly is a whole diffrent anmial.
as an example check the value of TRUE on your compiler then ask others to post the value used on there compielrs. while NULL and 0 may be the same in most cases there are may be an unlikely few where this may not be true. you have to consider there may be come cases where using interchanging 0 for null may cause problems. also dont forget the posiability that someone may redefine the value of NULL. a bad practice yes but entirely posiable.
dr voodoo - January 20, 2006 03:38 PM (GMT)
| QUOTE (myork @ Jan 19 2006, 11:01 PM) |
| I could not understand the logic in any of those arguments can you explain! |
Can you ever be certain (in std C++) that NULL is NULL and 0 is 0? No, so why bother?
PS: A compiler that would warn about miss use of 0 and of NULL would invalidate my arguments. However this is far from being usual. I don't even know a single compiler capable of this (GCC only checks for correct use of NULL).
| QUOTE |
| while NULL and 0 may be the same in most cases there are may be an unlikely few where this may not be true. |
Wrong, NULL is defined as 0. The conversion int => pointer is only defined for the compile time constant 0. Meaning the compiler will replace 0 by it's value. The conversion int => pointer isn't defined portably at all.
| QUOTE |
| also dont forget the posiability that someone may redefine the value of NULL. |
There might also be a macro such as
Well actually not as if is a keyword, but nearly all compilers allow this. Or how about defining i as virtual. That would surly mess up every loop.
No but now seriously, such people simply need to be shot.
myork - January 20, 2006 07:55 PM (GMT)
| QUOTE (dr voodoo @ Jan 20 2006, 10:38 AM) |
| QUOTE (myork @ Jan 19 2006, 11:01 PM) | | I could not understand the logic in any of those arguments can you explain! |
Can you ever be certain (in std C++) that NULL is NULL and 0 is 0? No, so why bother?
|
Still dont understand you argument.
In your ramblings you seem to be have veared off onto anther track and are proving that black is black or somthing else I don't understand.
Hippocrass - January 21, 2006 02:17 AM (GMT)
| QUOTE (myork @ Jan 18 2006, 02:25 AM) |
Unfortunately the article is bad. If the difference between HI and LOW is small than rand is not a very good random number generator espesially if you use the modulus operator '%'
The newer version of rand solves all the problems of rand.
Just replace:
rand with random srand with srandom
Now things should be OK. |
What header should I use with that?
I keep getting a messagae that srandom and random are undeclared.
FrozenKnight - January 21, 2006 06:47 PM (GMT)
Hmm guess he didn't want to use my dll :(
myork - January 22, 2006 10:36 PM (GMT)
| QUOTE (Hippocrass @ Jan 20 2006, 09:17 PM) |
What header should I use with that?
I keep getting a messagae that srandom and random are undeclared. |
O well you will just have to use the rand() and srand() functions.
Hippocrass - January 23, 2006 01:12 AM (GMT)
| QUOTE (myork @ Jan 22 2006, 10:36 PM) |
| QUOTE (Hippocrass @ Jan 20 2006, 09:17 PM) | What header should I use with that?
I keep getting a messagae that srandom and random are undeclared. |
O well you will just have to use the rand() and srand() functions.
|
Well, they work perfectly for what I need right now.
angain, though. Thanks.
myork - January 23, 2006 03:31 PM (GMT)
Just note that:
| CODE |
| int x = rand() % <RANGE>; |
Will not gice you a good value iff RANGE is small.
Because of the problem with rand() not producing very random values in the bottom few bits of x. (I am not a pure mathamitician so how bad, is somthing you may want to look up).
A better solution is:
| CODE |
int r = rand(); double d = static_cast<double>(RAND_MAX) / static_cast<doubel>(<RANGE>); int x = (static_cast<double>(r) / d); |
Which is a convoluted way of writting
| CODE |
| int x = static_cast<double>(rand()) * static_cast<double>(<RANGE>) / static_cast<double>(RAND_MAX); |
Which is probably safe to reduce too:
| CODE |
| int x = rand() * (<RANGE> / static_cast<double>(RAND_MAX)); |
Please note. The position of the '(' and ')' in the last expression is significant because of the automatic type conversion used by C/C++
dr voodoo - January 23, 2006 09:07 PM (GMT)
myork - January 23, 2006 09:14 PM (GMT)
| QUOTE (dr voodoo @ Jan 23 2006, 04:07 PM) |
| you do mean static_cast? |
yes. corrected