2

I'm working on C# Lab in Head First C# book.

When I push start button - dogs should run until one of them reach the finish. Each dog should run with random speed, but all of my dogs run with same speed ;/

Dogs initialization:

 GreyhoundArray[0] = new Greyhound(){
            MyPictureBox = GreyhoundPictureBox1,
            StartingPosition = GreyhoundPictureBox1.Left,
            RacetrackLenght = TrackPictureBox.Width - GreyhoundPictureBox1.Width,
            MyRandom = MyRandom                
        };
        GreyhoundArray[1] = new Greyhound(){
            MyPictureBox = GreyhoundPictureBox2,
            StartingPosition = GreyhoundPictureBox2.Left,
            RacetrackLenght = TrackPictureBox.Width - GreyhoundPictureBox2.Width,
            MyRandom = MyRandom
        };
        GreyhoundArray[2] = new Greyhound(){
            MyPictureBox = GreyhoundPictureBox3,
            StartingPosition = GreyhoundPictureBox3.Left,
            RacetrackLenght = TrackPictureBox.Width - GreyhoundPictureBox3.Width,
            MyRandom = MyRandom
        };
        GreyhoundArray[3] = new Greyhound(){
            MyPictureBox = GreyhoundPictureBox4,
            StartingPosition = GreyhoundPictureBox4.Left,
            RacetrackLenght = TrackPictureBox.Width - GreyhoundPictureBox4.Width,
            MyRandom = MyRandom
        };

Start button code:

private void StartButton_Click(object sender, EventArgs e)
    {
        timer1.Enabled = true;
    }

Timer code:

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

Run method:

public bool Run()
    {
        MyRandom = new Random();

        int distance = MyRandom.Next(1, 5);
        MyPictureBox.Left += distance;

        if(MyPictureBox.Left >= RacetrackLenght)
            return false;
        else
            return true;
    }
Ardoos
  • 88
  • 7
  • While I agree with the *underlying reason* for the problem being the duplicate proposed, it looks like there's already enough support for using a single instance here... so it would be helpful to have a separate answer for that, IMO. – Jon Skeet Jul 26 '15 at 08:44
  • @jon: As usual I read the stuff you write (or publish) carfully, but I just don't get it: This is simply one more question about why my Randoms are not random at all. – TaW Jul 26 '15 at 08:53
  • @TaW: Not obviously, because there's an *attempt* to use the same `Random` each time - see the way that the arrays are being initialized. It's just that that attempt is being foiled by creating a new instance within `Run`. – Jon Skeet Jul 26 '15 at 08:56
  • @JonSkeet I don't understand how your underlying answer is any different then the proposed duplicate. Both point to the fact the OP creating a new random instance where the randoms end up being the same. Saying that the OP has already created a single instance in initialization doesn't change the fact that the already provided duplicate will tell him *exactly* what he's doing wrong. – Yuval Itzchakov Jul 26 '15 at 10:08
  • @Yuval: I think we'll have to agree to differ. – Jon Skeet Jul 26 '15 at 10:34

1 Answers1

4

Your Run method creates a new instance of Random(). I suspect you don't want to do that - after all, you've already got a property called MyRandom which you're populating when you create the array.

Just take out the line:

MyRandom = new Random();

and see what happens.

As it is, you're creating a new instance of Random every time Run() is called... each of which is going to be seeded from the current time. That means if you call Run several times in quick succession (on any instance) you'll get the same distance most of the time, because the seed will be the same.

Without that extra creation, you'll be using the same instance of Random for all greyhounds, which means you'll be generating probably-different numbers for each call to Next. This is only okay if it's all in the same thread though - see my article on Random for details of various tricky aspects to randomness.

Your code already tries to do the right thing by setting the MyRandom property on initialization - it's just that it then messes it up by overwriting that property in the Run method.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194