简体   繁体   中英

Generating random numbers in an array

first post and a very noob question. I tried for many hours to get this program to work and eventually had to cheat and look up the answer from someone else.

When I run the following code, each greyhound array element receives the same random number. When I then initialized the array elements with aa random variable on the form, it then does generate different random numbers, but I don't understand why my initial code doesn't work. Can anyone please explain?

The code I had that didn't work: (relevant code)

firstly the class i made:

public class Greyhound
{
    public PictureBox MyPictureBox = new PictureBox();  //My picturebox object
    public int Location = 0;   //My location on the racetrack
    public Random Randomizer = new Random();

   public Run()
    {                                 
       Location +=  Randomizer.Next(15);
       MyPictureBox.Left = Location;

   }

}

And then the form:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
     }

     public Greyhound[] GreyhoundArray = new Greyhound[4];

     private void setupTrack()
        {
                  for (int i = 0; i < 4; i++)
            {
                GreyhoundArray[i] = new Greyhound();
            }
            GreyhoundArray[0].MyPictureBox = pictureBox1;
            GreyhoundArray[1].MyPictureBox = pictureBox2;
            GreyhoundArray[2].MyPictureBox = pictureBox3;
            GreyhoundArray[3].MyPictureBox = pictureBox4;
        }




       private void timer1_Tick(object sender, EventArgs e)
       {
           for (int i = 0; i < 4; i++)
           {
               GreyhoundArray[i].Run();
            }
       }

That's because by default Random constructor takes time as initial seed. If you do initialize all 4 elements at the same time, you're gonna have identical random generators. If you don't care about multi threading, make it static, so it'll be initialized once.

You are initializing the Greyhound instances in a loop very quick. That's why all Random isntances get the same seed (using the default constructor uses the system time as seed).

MSDN - Random Constructor:

The default seed value is derived from the system clock and has finite resolution. As a result, different Random objects that are created in close succession by a call to the default constructor will have identical default seed values and, therefore, will produce identical sets of random numbers

So you have to pass the Random to the constructor of Greyhound . Then use always the same Random instance in the loop.

public class Greyhound
{
    public PictureBox MyPictureBox = new PictureBox();  //My picturebox object
    public int Location = 0;   //My location on the racetrack
    private Random Randomizer = new Random();

    public Greyhound(Random randomizer)
    {
        this.Randomizer = randomizer;
    }

    public Run()
    {                                 
       Location +=  Randomizer.Next(15);
       MyPictureBox.Left = Location;
   }
}

Note that i've also made Randomizer to ensure that the constructor is used.

Here is the loop:

Random randomizer = new Random();
for (int i = 0; i < 4; i++)
{
    GreyhoundArray[i] = new Greyhound(randomizer);
}

The problem with your first code is that each instance of the class has its own random generator. If you create the instances close in time, then all the random generators will be seeded with the same start value, as the default seed is created using the system clock.

To use one random generator for all instances, you can create the random generator before creating the instances, and pass it to the constructor so that all instances have access to it:

public class Greyhound {

  public PictureBox MyPictureBox = new PictureBox();  //My picturebox object
  public int Location = 0;   //My location on the racetrack

  private Random Randomizer;

  public Greyhound(Random commonRandomizer) {
    Randomizer = commonRandomizer;
  }

  public Run() {                                 
    Location +=  Randomizer.Next(15);
    MyPictureBox.Left = Location;
  }

}

Usage:

Random rnd = new Random();
Greyhound[] GreyhoundArray = new Greyhound[4];
for (int i = 0; i < GreyhoundArray.Length; i++) {
  GreyhoundArray[i] = new Greyhound(rnd);
}

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