I admit I am not paying too much attention, but the first thing that struck me is that you are using a biased method to get numbers.
Furry Guy is correct in pointing this out.
rand() will always give you a number in [0, 2**n-1], which is
usually 0..32767 — not friendly for using remainder. To understand this, think about getting a number in a much more restricted range: 0..7.
If you were to want only three values ([0,7] % 3), you would have:
• 3 chances to get a 0: {0, 3, 6} % 3
• 3 chances to get a 1: {1, 4, 7} % 3
• 2 chances to get a 2: {2, 5} % 3 ← ONLY
TWO CHANCES!!??
Yes. This is called the “Pigeonhole Principle”, and it is the reason that using remainders on rand() are a “don’t do that” kind of thing. (Even though people have been doing it since rand() was created.)
The
correct way to fix this is to
simply ignore values that are too big for a proper remainder. This requires only a very little math:
x = rand();
while (x >= (RAND_MAX / range * range))
x = rand();
(Compiler issues and edge cases omitted.)
The easiest way is to just use C++’s modern RNG facilities, even if it was designed with really convoluted, hard-to-remember syntax. I find a little function helps.
1 2 3 4 5
|
long random( long min, long max )
{
static std::ranlux24 rng( std::chrono::system_clock::now().time_since_epoch().count() );
return std::uniform_int_distribution<long>( min, max )( rng );
}
|
Now you can get your perfectly distributed RGNs without any fuss:
|
int die_roll = random( 1, 6 );
|
Hope this helps.
(Disclaimer: code typed off the top of my head, meaning I may have typoed or otherwise erred.)