Multiple instances of Random class giving same number

  • (3 Pages)
  • +
  • 1
  • 2
  • 3

37 Replies - 6887 Views - Last Post: 06 June 2013 - 04:22 PM Rate Topic: -----

#1 admiralSCORCH62   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 8
  • Joined: 04-June 13

Multiple instances of Random class giving same number

Posted 04 June 2013 - 01:35 PM

Hi everyone

I'm going through the Head First C# and I am having an issue with the first lab "A Day At The Races".

Basically the form has one picture box that is the racetrack and then four smaller picture boxes will move across the racetrack until one reaches the end, their movement is determined by a randomly generated number.

I think that all of the random references are pointing to the same class because each picture box moves the exact same amount. I'm not sure how to change it so each reference points to a different object.


Here is the code in the Form1.cs, basically an array of GreyHound objects are created then in the for loop the randomiser is initiated

 

public Form1()
        {
            InitializeComponent();

            for (int i = 0; i < runners.Length; i++)
            {
                runners[i] = new Greyhound();
                runners[i].randomiser = new Random();
            }

            runners[0].myPictureBox = dog1;
            runners[1].myPictureBox = dog2;
            runners[2].myPictureBox = dog3;
            runners[3].myPictureBox = dog4;
        }






And this is the code where the Run method is called

 

private void raceButton_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < runners.Length; i++)
            {
                runners[i].Run();
            }
        }




This is the Greyhound classes Run method and all the classes fields at the top, which will move the picture boxes forward

 

public int startingPosition = 15;
        public int raceTrackLength = 367;
        public PictureBox myPictureBox = null;
        public int location = 0;
        public Random randomiser;
        public int distance;

        public bool Run()
        {
            int rand = randomiser.Next(15);

            Point pictureLocation = myPictureBox.Location;

            pictureLocation.X += rand;

            myPictureBox.Location = pictureLocation;

            int finish = pictureLocation.X;

            if (finish == raceTrackLength || finish > raceTrackLength)
            {
                return true;
            }

            else
            {
                return false;
            }
        }




If anyone can see what I did wrong I'd really appreciate it if you could point it out. I've looked at other solutions to see their random class but theirs looks the same as mine.

Thank you anyone one.

Is This A Good Question/Topic? 0
  • +

Replies To: Multiple instances of Random class giving same number

#2 andrewsw   User is offline

  • never lube your breaks
  • member icon

Reputation: 6833
  • View blog
  • Posts: 28,345
  • Joined: 12-December 12

Re: Multiple instances of Random class giving same number

Posted 04 June 2013 - 01:51 PM

public Random randomiser;

You haven't initialised this:

public Random randomiser = new Random();

(I'm sure every example you've encountered includes this line My apologies! )

This post has been edited by andrewsw: 04 June 2013 - 02:29 PM

Was This Post Helpful? 0
  • +
  • -

#3 admiralSCORCH62   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 8
  • Joined: 04-June 13

Re: Multiple instances of Random class giving same number

Posted 04 June 2013 - 01:59 PM

View Postandrewsw, on 04 June 2013 - 01:51 PM, said:

public Random randomiser;

You haven't initialised this:

public Random randomiser = new Random();

(I'm sure every example you've encountered includes this line :whistling:/> )



I should of said, I've went through several different versions and I've tried that before and it still has the same problem. I think the problem is each object is using the same randomiser and not their own. I've tried creating the objects separate and inside of an array.

Cheers though.
Was This Post Helpful? 0
  • +
  • -

#4 tlhIn`toq   User is offline

  • Xamarin Cert. Dev.
  • member icon

Reputation: 6536
  • View blog
  • Posts: 14,450
  • Joined: 02-June 10

Re: Multiple instances of Random class giving same number

Posted 04 June 2013 - 02:08 PM

You might consider seeding each new random when you make it, so it starts at a different value. Using the number of .Ticks from the CPU is a common tactic for this.

View Postandrewsw, on 04 June 2013 - 02:51 PM, said:

public Random randomiser;

You haven't initialised this:

public Random randomiser = new Random();

(I'm sure every example you've encountered includes this line :whistling:/> )


But he does initialize it before use. Otherwise it would be null and throw an exception. Look at the form constructor.
08 runners[i].randomiser = new Random();

Was This Post Helpful? 1
  • +
  • -

#5 pharylon   User is offline

  • D.I.C Head

Reputation: 41
  • View blog
  • Posts: 86
  • Joined: 01-September 12

Re: Multiple instances of Random class giving same number

Posted 04 June 2013 - 02:11 PM

The problem is each of the runners has it's own version of the randomiser. Since they're all instantiated at the same time (or, close enough anyway), they all have the same seed value, and will always "roll" the same number. Try this:

 

public Form1()
        {
            InitializeComponent();

            Random masterRandomizer = new Random();

            for (int i = 0; i < runners.Length; i++)
            {
                runners[i] = new Greyhound();
                runners[i].randomiser = masterRandomizer;
            }

            runners[0].myPictureBox = dog1;
            runners[1].myPictureBox = dog2;
            runners[2].myPictureBox = dog3;
            runners[3].myPictureBox = dog4;
        }





This brings back memories (I learned using Head First C# as well). If you want to see my solution, I still have it floating around. :)

This post has been edited by pharylon: 04 June 2013 - 02:19 PM

Was This Post Helpful? 4
  • +
  • -

#6 tlhIn`toq   User is offline

  • Xamarin Cert. Dev.
  • member icon

Reputation: 6536
  • View blog
  • Posts: 14,450
  • Joined: 02-June 10

Re: Multiple instances of Random class giving same number

Posted 04 June 2013 - 02:19 PM

I like it. Clean. No more objects than needed. Demonstrates the issue as being the opposite of what the OP thought: The problem arose not because all the references were to the same random, but because it SHOULD HAVE BEEN using the same instance and wasn't. Nice.
Was This Post Helpful? 0
  • +
  • -

#7 admiralSCORCH62   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 8
  • Joined: 04-June 13

Re: Multiple instances of Random class giving same number

Posted 04 June 2013 - 02:24 PM

View Postpharylon, on 04 June 2013 - 02:11 PM, said:

The problem is each of the runners has it's own version of the randomiser. Since they're all instantiated at the same time (or, close enough anyway), they all have the same seed value, and will always "roll" the same number. Try this:

 

public Form1()
        {
            InitializeComponent();

            Random masterRandomizer = new Random();

            for (int i = 0; i < runners.Length; i++)
            {
                runners[i] = new Greyhound();
                runners[i].randomiser = masterRandomizer;
            }

            runners[0].myPictureBox = dog1;
            runners[1].myPictureBox = dog2;
            runners[2].myPictureBox = dog3;
            runners[3].myPictureBox = dog4;
        }





This brings back memories (I learned using Head First C# as well). If you want to see my solution, I still have it floating around. :)/>


Thanks mate that works, so it seems creating a second randomiser to seed the first gives the first a different random each time, thanks again.

View Postpharylon, on 04 June 2013 - 02:11 PM, said:

This brings back memories (I learned using Head First C# as well). If you want to see my solution, I still have it floating around. :)/>


Sure mate, it's always cool to see how others did the same program differently.

Cheers tlhIn`toq as well mate, I didn't know how to access the CPU ticks so I tried using a stopwatch but that didn't work as well for some reason.
Was This Post Helpful? 0
  • +
  • -

#8 andrewsw   User is offline

  • never lube your breaks
  • member icon

Reputation: 6833
  • View blog
  • Posts: 28,345
  • Joined: 12-December 12

Re: Multiple instances of Random class giving same number

Posted 04 June 2013 - 02:24 PM

View PosttlhIn`toq, on 04 June 2013 - 09:08 PM, said:

But he does initialize it before use. Otherwise it would be null and throw an exception. Look at the form constructor.
08 runners[i].randomiser = new Random();

Aw right, sorry ;). I didn't pick up on that.
Was This Post Helpful? 0
  • +
  • -

#9 admiralSCORCH62   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 8
  • Joined: 04-June 13

Re: Multiple instances of Random class giving same number

Posted 04 June 2013 - 02:27 PM

View PosttlhIn`toq, on 04 June 2013 - 02:19 PM, said:

I like it. Clean. No more objects than needed. Demonstrates the issue as being the opposite of what the OP thought: The problem arose not because all the references were to the same random, but because it SHOULD HAVE BEEN using the same instance and wasn't. Nice.


I would have thought using the same object would give the same number while different ones would give different values?
Was This Post Helpful? 0
  • +
  • -

#10 pharylon   User is offline

  • D.I.C Head

Reputation: 41
  • View blog
  • Posts: 86
  • Joined: 01-September 12

Re: Multiple instances of Random class giving same number

Posted 04 June 2013 - 02:35 PM

View PostadmiralSCORCH62, on 04 June 2013 - 02:24 PM, said:

Thanks mate that works, so it seems creating a second randomiser to seed the first gives the first a different random each time, thanks again.


That's not exactly what's happening here. You're creating one single Random object. Note that the constructor is only called once - Random masterRandomizer = new Random(). After that, your'e passing a reference to that Random object to each of the Greyhounds. So there is no "second" randomiser. There's only one, shared by all the Greyhounds!



View PostadmiralSCORCH62, on 04 June 2013 - 02:27 PM, said:

I would have thought using the same object would give the same number while different ones would give different values?


They way the Random object works is, it takes a "seed" value and does some math on it, to result in a new pseudo-random number. Imagine a real die. If you knew the exact dimensions, weight, angle of throw, velocity, etc, you could predict exactly what side it would land on, right? All you'd need to know is it's starting state to predict the roll every time. The Random object is like that. The moment it's instantiated, you can know each and every "roll" it will make forever into the future, given it's starting state. And that starting state is the "seed value." By default, that seed value is the date and time of your computer. So if you create four Random objects at the same time, they will all have the same starting state, and will all roll the same number.

But, if we have all the Greyhounds use the same object, each time a Greyhound calls Random.Next() they are advancing the Random object one roll, and since all the Greyhounds are using the same object, it is advanced for all of them. Get it?


P.S. I feel this is obligatory:

Posted Image

This post has been edited by pharylon: 04 June 2013 - 02:48 PM

Was This Post Helpful? 2
  • +
  • -

#11 Michael26   User is offline

  • Futurama: Insert funny joke here
  • member icon

Reputation: 414
  • View blog
  • Posts: 1,664
  • Joined: 08-April 09

Re: Multiple instances of Random class giving same number

Posted 04 June 2013 - 02:40 PM

And CPU today are fast enough so if you create 4 Random objects you'll create almost identical seeds.
Was This Post Helpful? 0
  • +
  • -

#12 pharylon   User is offline

  • D.I.C Head

Reputation: 41
  • View blog
  • Posts: 86
  • Joined: 01-September 12

Re: Multiple instances of Random class giving same number

Posted 04 June 2013 - 02:45 PM

View PosttlhIn`toq, on 04 June 2013 - 02:19 PM, said:

I like it. Clean. No more objects than needed. Demonstrates the issue as being the opposite of what the OP thought: The problem arose not because all the references were to the same random, but because it SHOULD HAVE BEEN using the same instance and wasn't. Nice.


By the way, dude, I read several of your tutorials when I was staring out, and you've always been a big help when I've posted questions. Seeing you say that really made me smile. :D

Qapla!
Was This Post Helpful? 2
  • +
  • -

#13 admiralSCORCH62   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 8
  • Joined: 04-June 13

Re: Multiple instances of Random class giving same number

Posted 04 June 2013 - 02:50 PM

View Postpharylon, on 04 June 2013 - 02:35 PM, said:

View PostadmiralSCORCH62, on 04 June 2013 - 02:27 PM, said:

I would have thought using the same object would give the same number while different ones would give different values?


They way the Random object works is, it takes a "seed" value and does some math on it, to result in a new pseudo-random number. Imagine a real die. If you knew the exact dimensions, weight, angle of throw, velocity, etc, you could predict exactly what side it would land on, right? All you'd need to know is it's starting state to predict the roll every time. The Random object is like that. The moment it's instantiated, you can know each and every "roll" it will make forever into the future, given it's starting state. And that starting state is the "seed value." By default, that seed value is the date and time of your computer. So if you create four Random objects at the same time, they will all have the same starting state, and will all roll the same number.

But, if we have all the Greyhounds use the same object, each time a Greyhound calls Random.Next() they are advancing the Random object one roll, and since all the Greyhounds are using the same object, it is advanced for all of them. Get it?


I think I get this part, all four randomisers are created and updated at the same time, so the seed would be the same for all the randomisers becuase it uses the computer's time as the seed which would be the same. So the masterRandomizer is used to give a seed instead of the time.

Is the masterRandomizer then using a specific time as it's seed, but using a different calculation on that seed every time
runners[i].randomiser = masterRandomizer;


to give the randomiser a different value?


View Postpharylon, on 04 June 2013 - 02:35 PM, said:

That's not exactly what's happening here. You're creating one single Random object. Note that the constructor is only called once - Random masterRandomizer = new Random(). After that, your'e passing a reference to that Random object to each of the Greyhounds. So there is no "second" randomiser. There's only one, shared by all the Greyhounds!


So it's creating a single new Random which is used as the seed of randomiser?

Cheers for all your help mate, I really appreciate it.
Was This Post Helpful? 0
  • +
  • -

#14 Curtis Rutland   User is offline

  • (╯□)╯︵ (~ .o.)~
  • member icon


Reputation: 5106
  • View blog
  • Posts: 9,283
  • Joined: 08-June 10

Re: Multiple instances of Random class giving same number

Posted 05 June 2013 - 07:50 AM

Quote

So it's creating a single new Random which is used as the seed of randomiser?


No. You need to understand how reference types work. You're only creating one instance of a Random object. That's stored in memory, and your masterRandomizer variable stores a pointer to that object. Then, when you call this line: runners[i].randomiser = masterRandomizer;, you're copying the pointer into the runner's randomizer variable.

What that means is that you never have more than one instance of a Random object. You have several variables that all hold pointers that point to the single instance of Random.

That's a good thing, in this case. Best practice with the Random class is to create one, and re-use it. That way, you don't need to provide seeds, just let the system seed it with the current time and move on.

This post has been edited by tlhIn`toq: 05 June 2013 - 07:56 AM
Reason for edit:: Changed 'copy' to 'instance' so it doesn't sound like duplicating/cloning of an instance

Was This Post Helpful? 2
  • +
  • -

#15 admiralSCORCH62   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 8
  • Joined: 04-June 13

Re: Multiple instances of Random class giving same number

Posted 05 June 2013 - 10:05 AM

View PostCurtis Rutland, on 05 June 2013 - 07:50 AM, said:

Quote

So it's creating a single new Random which is used as the seed of randomiser?


No. You need to understand how reference types work. You're only creating one instance of a Random object. That's stored in memory, and your masterRandomizer variable stores a pointer to that object. Then, when you call this line: runners[i].randomiser = masterRandomizer;, you're copying the pointer into the runner's randomizer variable.

What that means is that you never have more than one instance of a Random object. You have several variables that all hold pointers that point to the single instance of Random.

That's a good thing, in this case. Best practice with the Random class is to create one, and re-use it. That way, you don't need to provide seeds, just let the system seed it with the current time and move on.


I think I understand what your saying.

 public Random randomiser; 


This is created in the greyhound class but it is not initiated, so there is no random class created yet, just a reference pointing to nothing.

Then in the Form1 class

 Random masterRandomiser = new Random();
for (int i = 0; i < runners.Length; i++)
            {
                runners[i] = new Greyhound();
                runners[i].randomiser = masterRandomiser;
            }



This is creating a reference called masterRandomiser, which is initiated so it is pointing to a single Random object. The randomiser reference in each of the Greyhound classes then all point to the same object as the masterRandomiser in the for loop.


So does that mean that since they all point to the same object, every time they are used they use the same seed, but perform a different calculation on the seed so each returns a different number?
Was This Post Helpful? 0
  • +
  • -

  • (3 Pages)
  • +
  • 1
  • 2
  • 3