Some questions about game programming

Started by
11 comments, last by instinKt 16 years, 10 months ago
Hi I am reading Beginning C++ through Game Programming and it is not too bad. My first question is, in one of his exaample(guess my number I think), he uses the rand() function. Having only lightly touched upon this function in my class at school, all I know is that it creates a random number. Is this the case? He uses srand() as well, is this a different type of function, he uses time(0) inside the srand(time(0)), what does this mean and do? Why 0, why not 1? Just looking for clarification, is this the noly way to achieve what the autor wants? Here is one of his examples:

// Die Roller
// Demonstrates generating random numbers

#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;

int main()
{

	srand(time(0)); // seed random number generator based on current time

	int randomNumber = rand(); // generate random number

	int die = (randomNumber % 6) + 1; // get a number between 1 and 6
	cout << "You rolled a " << die << endl;

    return 0;
}


Here is another:
 
// Guess My Number
// The classic number guessing game

#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;

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

	int theNumber = rand() % 100 + 1; // random number between 1 and 100
	int tries = 0, guess;
    
	cout << "\tWelcome to Guess My Number\n\n";

	do
	{
		cout << "Enter a guess: ";
		cin >> guess;
		++tries;

		if (guess > theNumber)
			cout << "Too high!\n\n";

		if (guess < theNumber)
			cout << "Too low!\n\n";

	} while (guess != theNumber);

	cout << "\nThat's it! You got it in " << tries << " guesses!\n";

    return 0;
}

Why does he use these functions as he does?
Advertisement
The first thing you should understand is that the function rand() is only a pseudo-random number generator... meaning it doesn't actually give truely random values.

The function srand() is used to "seed" the random number generator. This essentially tells rand() the number to start with when creating a random number. The reason the author passes the time() function is because that will most likely return a different value for each application session, and thus, greatly increase the appearance of randomness in the app.

I say "the appearance of randomness" because, again, rand() is only pseudo-random. If you don't seed the generator by calling srand() you will get very predictable, non-random return values.

As for why he's passing 0 to time() instead of any other value, I'm not completely sure, I'd have to see the documentation for the function...it probably has to do with how time() internally decides what value to return.

Hope that clears things up.

EDIT: One thing I just remembered...NEVER ever ever call srand() more than once in your application. It essentially defeats the purpose and reverts rand() back to it's non-random status.
Look up these functions in MSDN or any other C or C++ reference.
srand is a function that sets the "seed" from which random numbers are generated. Without it, you'll always get the same results. srand takes a single number from which random calculations (with calls to rand) are made. In order to have a "random" seed, you give srand as a parameter time(0), which is a function that returns the elapsed time your computer has been running in milliseconds or something similar. This value is random enough so that it is a good seed for random-number generations.

Remember : a computer cannot create actual random numbers, they can create pseudo-random numbers using such computations which often require "seeding" (giving a seed).
Okay, first of all srand. As a tangent, I think that a good tutorial for random numbers would be to show the user how to implement their own pseudo-random number generator. Except I've never done it myself, so anything I implement will likely be pretty sucky in terms of distribution. End tangent.

How random number generators tend to work is, they take the last random value generated, perform a couple of math operations on it, and then spit out that new value as the next number in the list. The problem comes from the fact that if you start with the same value then every subsequent value will always be the same each time you run the program. It's like if someone says "pick a number" and then they give a set of steps like "add 3, divide by two, XOR that with 0xF3A002EB, then subtract 7" then you'll always get the same value if you always pick the same number.

This is where srand comes in, in relation to rand. All you do is give srand a different number each time you run the program and then the problem mentioned in the last paragraph won't happen! But this brings us a new problem: how to give srand a different number each time the program runs? We can't use a random number, because that's like a chicken and the egg type problem that we're still trying to solve. This is where time comes in. If you can find a way to pick a different number at the start then you'll get a different answer. And what number is different every time you run the program? The time!

This leads me to your second query concerning the time function. Let's take a look at some documentation , shall we?

It says, basically, that you can pass a pointer to a time_t object (I'm pretty sure it's just a typedef for a large integer type) and it will fill that location in memory with the data. And time also returns a time_t object or -1 on error.

"Why does it do this?" I asked myself. After thinking about it, I decided the most likely reason was that you could then use the time function's return value as error checking. You could do something like:

time_t currentTime;if( time(&currentTime) == -1){  std::cout << "Could not retrieve time." <<std::endl;  // do some error handling or something}

I could be wrong, I've never used it that way. And who ever heard of time failing?

Hope that help.s

C++: A Dialog | C++0x Features: Part1 (lambdas, auto, static_assert) , Part 2 (rvalue references) , Part 3 (decltype) | Write Games | Fix Your Timestep!

Just a side-note, for small project you shouldn't worry about wether rand() is good enough or not, being pseudorandom. Just go with it and don't worry too much if it works for you. ;) On the other hand, if you can learn better RNGs early on and make using them a habit, you'll be doing yourself a favor - you'll want to move to something better eventually...

To answer your first question, rand() generates a "random" value between 0 and 32767. You can manipulate this value with a modulo operation to return a range of values between 0 and (x-1) (ex: rand()%6 would return a value between 0 and 5.) Obviously you can't return a value higher than 32767.

Rand's values are generated by doing some crazy mathematical operation that causes the result to overflow, leaving the remaining value "random." Random in the sense that you wouldn't be able to guess the next one short of using a calculator. From this, it shouldn't take too long to understand why it's not all that hot: it doesn't actually generate anything random.

A quick peek at Google's results for "rng algorithms" should turn up a few interesting ones. The Mersenne Twister is a popular, though advanced, way of generating pseudo-random numbers; it's fairly performant and random - might be worth a look. However, you should be aware that no matter what, a computer cannot generate any "true" random numbers - at best you can get pseudorandom values with a very, very low correlation between successive generated values.
Just to be picky. Wouldn't time(0) technically destroy the universe? As Washu would put it anyway. In other words, undefined behavior?

Since NULL is not necessarily 0 and 0 is not necessarily a pointer? :D

Usually hate to be picky but recent things I have learned is that I've been taught C and C++ all wrong. Meaning I've been taught what works, not what IS C and C++. So time(0) is probably not a good habit to get used to.
Thanks that helps alot

So srand() can not be placed into a varialbe like ran() right?

So everytime you use rand() it will generate a pseudo random number?
Quote:Original post by bluefox25
Thanks that helps alot

So srand() can not be placed into a varialbe like ran() right?

So everytime you use rand() it will generate a pseudo random number?


For the first question, if you DID try to use the return value of srand you would get a compiler error, because srand doesn't return any value. Hence you Can't assign the result of srand to a variable!

Second question: Yes, basically.

I wasn't going to originally, but I'll show how you could try writing your own srand and rand functions so you can see what's going on.
#include <iostream>#include <ctime>// implementation taken from http://www.linuxmanpages.com/man3/rand.3.phpstatic unsigned long next = 1;/* RAND_MAX assumed to be 32767 */int myrand(void) {	next = next * 1103515245 + 12345;	return((unsigned)(next/65536) % 32768);}void mysrand(unsigned seed) {	next = seed;}int main(){	mysrand( std::time(0) );	std::cout << "Some random numbers: " << myrand() << " " << myrand() << std::endl;}


removed the NULL after rip-off's post.
Hope that helps.

[Edited by - nobodynews on June 1, 2007 3:47:13 PM]

C++: A Dialog | C++0x Features: Part1 (lambdas, auto, static_assert) , Part 2 (rvalue references) , Part 3 (decltype) | Write Games | Fix Your Timestep!

Quote:Original post by instinKt
Just to be picky. Wouldn't time(0) technically destroy the universe? As Washu would put it anyway. In other words, undefined behavior?

Since NULL is not necessarily 0 and 0 is not necessarily a pointer? :D

Usually hate to be picky but recent things I have learned is that I've been taught C and C++ all wrong. Meaning I've been taught what works, not what IS C and C++. So time(0) is probably not a good habit to get used to.


It is very much defined.

0 is the preferred way to set a variable to null in C++. NULL boils down to the same thing, but is a preprocessor macro only available if you include certain headers.

time(0) should be used. the literal 0 *is* a pointer, if a pointer is assigned to it. It is only an integer if an integer is assigned to it. It also has special meaning if included in a virtual function declaration too.

This topic is closed to new replies.

Advertisement