Reputation: 14921
I have been writing some C# code for a training exercise, in which I had to create an array of random rectangles.
Problem being that the rectangle being produced by my GetRandomRectangle function was always the same.
I was using System.Random
to generate the coordinates for the rectangle.
I've realised that it was because the Random object was beign created with the default constructor, and so had the same seed. I've modified it to get a different seed for each rectangle now, and it works fine.
The question is - how does it decide on the 'default seed'? I've noticed that it doesn't seem to change over time either, a rectangle created with seed 2 will always be given the same dimensions.
It's probably something that I could Google, but it's nice to hear opinions and info from you guys as well.
Thanks :)
Upvotes: 1
Views: 3494
Reputation: 14593
Im no C# expert but this might work.
public Rectangle GetRandomRectangle()
{
static Random rng=new Random();
// create the rectangle using rng
}
Upvotes: 0
Reputation: 10391
I used to use that as well, but I found the class to produce far from sufficiently random values. I switched to the random functions within the cryptography namespace instead. Here's a VERY simple version without error checking or screen size conversion:
byte[] randomBytes = new byte[4];
RandomNumberGenerator numberGenerator = System.Security.Cryptography.RandomNumberGenerator.Create();
numberGenerator.GetNonZeroBytes(randomBytes);
int x = randomBytes[0];
int y = randomBytes[1];
int width = randomBytes[2];
int height = randomBytes[3];
System.Drawing.Rectangle block = new Rectangle(x, y, width, height);
Upvotes: 1
Reputation: 48476
Actually, the default Random()
constructor is time-dependant and should provide different output upon running the application a second time. If you were getting the same rectangle every time, something else must have been going on.
Providing the seed manually will always give you the same sequence of pseudo-random numbers.
You should only need to instantiate a single Random
object to generate all your random numbers. Don't create a new instance for each rectangle.
Upvotes: 1
Reputation: 1220
When you use a seed, this means that you want the same sequence starting from that seed
Try the constructor without seed
Upvotes: 0
Reputation: 269278
The default seed is taken from the system clock.
I'm guessing that your GetRandomRectangle
method was being called in quick succession and instantating a new instance of Random
each time. When you do this, each instance of Random
will take the same seed from the system clock, which is why your method created the same rectangle each time.
One solution is to create one instance of Random
and pass that into your method:
Random rng = new Random();
Rectangle foo = GetRandomRectangle(rng);
Rectangle bar = GetRandomRectangle(rng);
Rectangle baz = GetRandomRectangle(rng);
// ...
public Rectangle GetRandomRectangle(Random rng)
{
// create the rectangle using rng
}
Upvotes: 11