Possible Duplicate:
Why does it appear that my random number generator isn't random in C#?
How can I generate truly (not pseudo) random numbers with C#?
I've created a dice game where the dice is based on a percentile, 1-100.
public static void Roll()
{
Random rand = new Random((int)DateTime.Now.Ticks);
return rand.Next(1, 100);
}
But I don't feel like it's a real random based on current time.
If I do
for (int i = 0; i < 5; i++)
{
Console.WriteLine("#" + i + " " + Roll());
}
They would all be the same values, because the DateTime.Now.Ticks
didn't change, it seeded the same number.
I was thinking I could generate a new random seed if the seed was the same due to the current time, but it doesn't feel like an honest "re-roll"
What should I do to try and replicate a close to real/honest dice roll? Should I use the RNGCryptoServiceProvider
class to generate rolls instead?
You should create your Random class only once outside your Roll function and seed it with a unique value.
You are recreating your Random each time you call Roll which causes the 'not random numbers'.
DateTime.Now.Ticks
only has a resolution of approximately 16ms, so if you create aRandom
with that overload multiple times within a 16ms "slot" they will all be seeded with the same value and therefore you will get the same sequence.Initialize your
Random
outside your loop so that a singleRandom
sequence is produced, rather than creating it each time within the loop which could result inRandoms
being seeded with the same value and so produce the same sequence.Update
My previous point that the default constructor initialized
Random
with CPU ticks was incorrect, the default constructor actually uses Environment.TickCount which is:Which still has a low resolution. If you make multiple instances of
Random
in quick succession, they can easily be created within the same time slot and therefore have the same seed value, and create the same sequence. Create a single instance ofRandom
and use that.Update
Further to your comments, if you wish to generate a random sequence across multiple threads, please see the following Jon Skeet article which discusses a thread-safe wrapper:
https://codeblog.jonskeet.uk/2009/11/04/revisiting-randomness
Pseudo-random number generators like
Random
should only be seeded once, so:(Note I made the return value
int
rather thanvoid
; theRoll
function as quoted in the question results in a syntax error.)But your title says "Creating a true random".
Random
won't do that for you, it's a pseudo-random number generator, meaning it's deterministic, just hard to predict if you don't know the seed. Usually that's good enough for most purposes, but if you need real randomness, you need an entropy source. http://random.org is one popular one.I'm assuming that you are calling the
Roll()
method so quickly thatNow.Ticks
is the same?The simplest way to get around this would be rather than to create a new
Random()
instance each time you callRoll()
create a static variable to hold a single instance ofRandom()
.If this is a serious game with money at stake then: Yes.
The usual way to use random number generators is to seed them once, save them and call on them repeatedly throughout your programme. As long as you seed from a suitable value at the start, you should get acceptable randomness - assuming the generator you're using is using a function returning things which are suitably random for your purposes. So, save your Random instance outside the Roll() function, seed it the first time it's used, then just call Next() on it each time you need another number.
When you get right down to it, there's no such thing as true random number generation on a computer, only pseudorandom sequences based on a seed. However, humans are terrible at identifying randomness, so it's usually okay.