5

I am working on the first lab of headfirst C#. I ran into a problem in my program that the dogs go at the same speed. I cant figure out why they do so, because in my eyes every object instance get a random 1 to 5 pixels added to its X location. The randomness of this should make enough of a difference.

So because I dont want to post my entire set of classes of Lab 1 I recreated a small and independent version with only two dogs racing, and without the betting aspect.

Form1.Designer contains: -Two pictureboxes with a hound in it. -a Start button

Greyhound.cs class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;

namespace test
{
    public class Greyhound
    {
        public int DogID;
        public PictureBox myPictureBox;
        public Point StartingPosition;
        public Point CurrentPosition;
        public Random Randomizer;

        public bool Run()
        {
            int AddDistance = Randomizer.Next(1, 7);
            CurrentPosition.X += AddDistance;
            myPictureBox.Location = CurrentPosition;

            if (CurrentPosition.X > 600)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public void ReturnToStart()
        {
            CurrentPosition = StartingPosition;
            myPictureBox.Location = StartingPosition;
        }
    }
}

Form1.cs class:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

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

        private void timer1_Tick(object sender, EventArgs e)
        {
            Greyhound One = new Greyhound() { DogID = 1, myPictureBox = pictureBox1, StartingPosition = pictureBox1.Location, CurrentPosition = pictureBox1.Location, Randomizer = new Random() };
            Greyhound Two = new Greyhound() { DogID = 2, myPictureBox = pictureBox2, StartingPosition = pictureBox1.Location, CurrentPosition = pictureBox2.Location, Randomizer = new Random() };
            if (One.Run())
            {
                timer1.Enabled = false;
                MessageBox.Show("Dog One WON!");

            }
            else if (Two.Run())
            {
                timer1.Enabled = false;
                MessageBox.Show("Dog Two WON!");
            }


        }

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

Can anyone see something wrong with the way this is created? A reason for why the dogs would run at the same speed instead of random 1 to 5 pixels per time.

Ashley Medway
  • 7,151
  • 7
  • 49
  • 71
user2953063
  • 437
  • 2
  • 6
  • 10

2 Answers2

2

Instead of passing to each dog a new Random do this:

Random rnd = new Random();
Greyhound One = new Greyhound() { DogID = 1, myPictureBox = pictureBox1, StartingPosition = pictureBox1.Location, CurrentPosition = pictureBox1.Location, Randomizer = rnd };
Greyhound Two = new Greyhound() { DogID = 2, myPictureBox = pictureBox2, StartingPosition = pictureBox1.Location, CurrentPosition = pictureBox2.Location, Randomizer = rnd  };

Explanation
That happens because Random object are in reality semi-random, they generate a sequence of random number that are calculated by using a given seed number. This seed is generated automagically at runtime if you use the Random() constructor. But if you create two Random in sequence, as you was doing in the your code, the seed generated will be equals and so will be the numbers generated by the two randomizer.

You can try with a simpler example:

        //Your two dogs have two new Random instantiated in sequence.
        //The two random numbers will be always the same
        bool areTheSame = new Random().Next() == new Random().Next();
        Console.WriteLine("two dogs with two Random are the same? "+ areTheSame);
        Random rnd = new Random();

        //The two dogs have now the same random object.
        //The two random numbers will be almost always different. Almost because the numbers are random and two or more equals number can occur in sequence.
        areTheSame = rnd.Next() == rnd.Next();
        Console.WriteLine("two dogs using the same random are the same? ~" + areTheSame);
        Console.ReadLine();
Fabio Marcolini
  • 2,315
  • 2
  • 24
  • 30
2

The problem is with the Random class. When you create a new object without a parameter it uses the system clock:

By default, the parameterless constructor of the Random class uses the system clock to generate its seed value, while its parameterized constructor can take an Int32 value based on the number of ticks in the current time. However, because the clock has finite resolution, using the parameterless constructor to create different Random objects in close succession creates random number generators that produce identical sequences of random numbers.

You should use just one Random class and insert different generated values as your starting speed.

Johnny Graber
  • 1,427
  • 5
  • 27
  • 33