Randomness

Read time: 9 minutes (2416 words)

In many programming projects, you need to inject a bit of randomness into your world. Games are an example of this (or simulations, if you prefer). The big question is how do we get a precisely controlled machine to do anything resembling randomness?

Random Generators

Fortunately, this problem was solver long ago. The C/C++ language has “random” functions that will return a random number for your use. There is a big problem with these functions, though. If you call them over and over, you do get random values back, but if you run the same program twice, you get the same random numbers the second time. Hardly “random”.

Mathematicians hate this!

Random Seeding

The preferred solution to this problem involves setting up your code so it jumps into the repeatable sequence of random numbers at a ransom spot. If you do not record that spot, you will not be able to repeat that starting point and your code will seem more random.

This is called “seeding” the random number generator.

Seed Tactics

There are many schemes in use to pick a seed value. The one we will look at involves the system clock. You probably cannot precisely make your program run twice with the same clock time value (it takes a few hundred youear to even get to the same time value, since it is stored as a 64-bit integer number internally!)

So, we get the current time from the OS, and use that number to start our random sequence.

Time for some code:

include/Random.h
1
2
3
4
5
6
7
#pragma once

class Random {
    public:
        void seed( void );
        int get_random( int min, int max );
};

The idea here is to provide a way to get a random number between two specified values. According to the documentation for the real random functions:

  • rand() - returns a pseudo-random number between 0 and RAND_MAX (at least 32767)
  • srand() - uses an unsigned integer value to “seed” the rand() function

We will use the system time() function, which returns an unsigned long as our source for the seed value:

Here is the code needed to get our random numbers:

lib/Random.cpp
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#include <cstdlib>
#include <iostream> // needed for time
using namespace std;
#include "Random.h"

void Random::seed( void ) {
    srand((unsigned) time(0));
}

int Random::get_random( int min, int max ) {
    int range = max - min + 1;
    return min + (rand() % range);
}

Notice that we use the mod operator to limit the range of values we accept from rand() to the range we are interested, and add the random offset to the starting number we set.

This will give you a nice generator you can use to separate cars on the highway to get started, and any other operation where setting some value is needed. Rather that asking you to do that, we let the random number generator pick things:

initial_range = get_random(1,MAX_LANES);        // set the lane to one of those available

Somewhere in the initialization code, you will need to set up the random number generator object and make is start with a single call to the seeding method (in the constructor).