简体   繁体   中英

Random number generation in C#

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 :)

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
}

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.

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);

When you use a seed, this means that you want the same sequence starting from that seed

Try the constructor without seed

Im no C# expert but this might work.

 public Rectangle GetRandomRectangle()
 {
      static Random rng=new Random();
      // create the rectangle using rng
 }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM