I’m working on a little game for some friends that involves rolling five dice on a board and came across an interesting little problem, which I’ll illustrate with a very small dummy program. Here we have a simple die class for creating individual die objects:
namespace DiceRoller
{
class Die
{
public int Face { get; private set; }
private const int maxRoll = 6;
private Random ran = new Random();
// Constructor
public Die()
{
Roll();
}
// Roll the die
public int Roll()
{
Face = ran.Next(maxRoll) + 1;
return Face;
}
}
}
And a small console program that will instantiate 5 dice and roll all five of them, 5 times.
namespace DiceRoller
{
class Program
{
static void Main(string[] args)
{
Die[] dice = { new Die(),
new Die(),
new Die(),
new Die(),
new Die()
};
for (int j = 0; j < 5; j++)
{
for (int i = 0; i < dice.Length; i++)
{
Console.Write(dice[i].Roll());
}
Console.WriteLine("\n");
}
Console.ReadLine();
}
}
}
And here is the output.
![]()
Whoa! Not very random. The default .NET random number generator appears to be using the system time to generate the random numbers. Because our calls to ran.Next() are so close together, we’re getting mostly the same result. There are a couple of ways to fix this. One option is to tell the thread to stop executing for some time before the roll, by using Thread.Sleep(10) at the start of the Roll() method. This works, but it’s ugly.
A better solution is to make the Random object in the Die class a static member. This way, every die will share the same Random, and so each time ran.Next() is called it iterates the random number on the same object. This solution is perfect. You only need to change one line in the Die class:
And the result:
![]()
Perfect! In this case it was easy to see the problem and very simple to fix, but the moral of the story is, be careful with the RNG if you’re using it for anything non-trivial, especially when you’re generating multiple numbers from different instances of Random.
Post a Comment