O'Reilly Forums: Lab #1 - Day At The Races - O'Reilly Forums

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

Lab #1 - Day At The Races

#1 User is offline   wunderwaffe 

  • Active Member
  • PipPip
  • Group: Members
  • Posts: 26
  • Joined: 14-January 14

Posted 15 January 2014 - 03:22 AM

Hello,

I've started on the GUI and animation of the dogs.

Rather than all dogs moving smoothly at once, Dog1 moves at lightning speed to the end and an alert pops up. Dog 2 then runs and alert pops up. The same happens for the other dogs.

I'll post relevant code if you tell me what you'd like to see.

Thanks,

Seve
0

#2 User is offline   FrontalMonk 

  • New Member
  • Pip
  • Group: Members
  • Posts: 6
  • Joined: 15-January 14

Posted 15 January 2014 - 01:01 PM

Please do post your code, I completed this lab just last week and should be able to help you spot whatever may have gotten messed up there.
0

#3 User is offline   wunderwaffe 

  • Active Member
  • PipPip
  • Group: Members
  • Posts: 26
  • Joined: 14-January 14

Posted 16 January 2014 - 01:24 AM

View PostFrontalMonk, on 15 January 2014 - 01:01 PM, said:

Please do post your code, I completed this lab just last week and should be able to help you spot whatever may have gotten messed up there.


Thanks for replying.

Sure thing:

Greyhound.cs

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

namespace dugs
{
    public class Greyhound
    {
        public Point StartingPosition;
        public int RaceTrackLength;
        public PictureBox MyPictureBox;
        public int Location = 0;
        public Random Randomizer;

        public bool Run()
        {
            Randomizer = new Random();
            Location = StartingPosition.X;
            while (Location <= RaceTrackLength)
            {
                Point p = MyPictureBox.Location;
                int distance = Randomizer.Next(1, 4);
                Location += distance;
                p.X += distance;
                MyPictureBox.Location = p;
                //System.Threading.Thread.Sleep(50);
                //System.Diagnostics.Debug.WriteLine("location: " + Location + " Distance: " + distance + " Length: " + RaceTrackLength);
            }
            return true;
            
    
        }

        public void TakeStartingPosition()
        {
            MyPictureBox.Location = StartingPosition;
        }

    }
}


Form1.cs

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 dugs
{
    public partial class form1 : Form
    {
        Greyhound g1;
        Greyhound g2;
        Greyhound g3;
        Greyhound g4;
        Greyhound[] greyRay;
        int minBet = 5;

        public form1()
        {
            InitializeComponent();
            minBet = 5;
            g1 = new Greyhound() { StartingPosition = pictureBox2.Location, RaceTrackLength = (pictureBox1.Width - pictureBox2.Width -30), MyPictureBox = pictureBox2};
            g2 = new Greyhound() { StartingPosition = pictureBox3.Location, RaceTrackLength = (pictureBox1.Width - pictureBox2.Width- 30), MyPictureBox = pictureBox3 };
            g3 = new Greyhound() { StartingPosition = pictureBox4.Location, RaceTrackLength = (pictureBox1.Width - pictureBox2.Width- 30), MyPictureBox = pictureBox4 };
            g4 = new Greyhound() { StartingPosition = pictureBox5.Location, RaceTrackLength = (pictureBox1.Width - pictureBox2.Width - 30), MyPictureBox = pictureBox5 };

            greyRay = new Greyhound[4];
            greyRay[0] = g1;
            greyRay[1] = g2;
            greyRay[2] = g3;
            greyRay[3] = g4;
        }
        

        private void button1_Click(object sender, EventArgs e)
        {
            timer1.Start();
        }

        private void menuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {

        }

        private void label1_Click(object sender, EventArgs e)
        {

        }

        private void pictureBox2_Click(object sender, EventArgs e)
        {

        }

        private void button3_Click(object sender, EventArgs e)
        {
            foreach (Greyhound g in greyRay)
            {
                g.TakeStartingPosition();
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            foreach (Greyhound g in greyRay)
            {
                if (g.Run())
                {
                    timer1.Stop();
                    
                }
                MessageBox.Show("Dog " + g.StartingPosition + " wins");
                g.TakeStartingPosition();
            }
        }
    }
}

This post has been edited by wunderwaffe: 16 January 2014 - 02:37 AM

0

#4 User is offline   FrontalMonk 

  • New Member
  • Pip
  • Group: Members
  • Posts: 6
  • Joined: 15-January 14

Posted 16 January 2014 - 06:14 AM

So, I noticed a couple things here:

First, in your Greyhound class, the Run method is set to do a while loop.
            while (Location <= RaceTrackLength)
            {
                Point p = MyPictureBox.Location;
                int distance = Randomizer.Next(1, 4);
                Location += distance;
                p.X += distance;
                MyPictureBox.Location = p;
                //System.Threading.Thread.Sleep(50);
                //System.Diagnostics.Debug.WriteLine("location: " + Location + " Distance: " + distance + " Length: " + RaceTrackLength);
            }
            return true;
            
    
        }


The problem with this, is it's just going to keep going through this step, advancing the position of the first dog you send until Location > RaceTrackLength, then it returns true. What you probably want is something more like this:
if (Location <= RaceTrackLength)  //check if the dog has finished the race, if it hasn't, do the stuff
{
//Do stuff
return false;  //tell the main loop that the dog hasn't finished, and to continue cycling through to the other dogs
}
else  //the dog did finish the race
return true;  //tell the main loop that the dog won, so it can stop


The "else" statement isn't really necessary, just there for clarity's sake.

Also, your Timer_Tick method has a couple flaws. You put this:

        private void timer1_Tick(object sender, EventArgs e)
        {
            foreach (Greyhound g in greyRay)
            {
                if (g.Run())
                {
                    timer1.Stop();
                    
                }
                MessageBox.Show("Dog " + g.StartingPosition + " wins");
                g.TakeStartingPosition();
            }
        }


So what's happening is you check every tick to go through the greyRay to advance the dogs, then because these statements are outside the if, a messagebox displays saying "Dog 22 wins" or whatever you set his startingPosition value to. Then it resets the dog's position. So, maybe do something like this:
for(i=0, i<greyRay.length;i++)
{
     if(greyRay[i].run())
     {
           timer1.stop();
           MessageBox.Show("Dog #" + i + " wins!");
           foreach(Greyhound g in greyRay)
                g.TakeStartingPosition();
     }
}


Because what this piece of code is doing is running a loop through each of the dogs in the array, and running the run() method, which moves each one up a random amount...then only if it comes back true does it stop the timer, show the winner message box, and reset all the positions.

Hope this helps!
0

#5 User is offline   wunderwaffe 

  • Active Member
  • PipPip
  • Group: Members
  • Posts: 26
  • Joined: 14-January 14

Posted 16 January 2014 - 07:37 AM

View PostFrontalMonk, on 16 January 2014 - 06:14 AM, said:

So, I noticed a couple things here:

First, in your Greyhound class, the Run method is set to do a while loop.
            while (Location <= RaceTrackLength)
            {
                Point p = MyPictureBox.Location;
                int distance = Randomizer.Next(1, 4);
                Location += distance;
                p.X += distance;
                MyPictureBox.Location = p;
                //System.Threading.Thread.Sleep(50);
                //System.Diagnostics.Debug.WriteLine("location: " + Location + " Distance: " + distance + " Length: " + RaceTrackLength);
            }
            return true;
            
    
        }


The problem with this, is it's just going to keep going through this step, advancing the position of the first dog you send until Location > RaceTrackLength, then it returns true. What you probably want is something more like this:
if (Location <= RaceTrackLength)  //check if the dog has finished the race, if it hasn't, do the stuff
{
//Do stuff
return false;  //tell the main loop that the dog hasn't finished, and to continue cycling through to the other dogs
}
else  //the dog did finish the race
return true;  //tell the main loop that the dog won, so it can stop


The "else" statement isn't really necessary, just there for clarity's sake.

Also, your Timer_Tick method has a couple flaws. You put this:

        private void timer1_Tick(object sender, EventArgs e)
        {
            foreach (Greyhound g in greyRay)
            {
                if (g.Run())
                {
                    timer1.Stop();
                    
                }
                MessageBox.Show("Dog " + g.StartingPosition + " wins");
                g.TakeStartingPosition();
            }
        }


So what's happening is you check every tick to go through the greyRay to advance the dogs, then because these statements are outside the if, a messagebox displays saying "Dog 22 wins" or whatever you set his startingPosition value to. Then it resets the dog's position. So, maybe do something like this:
for(i=0, i<greyRay.length;i++)
{
     if(greyRay[i].run())
     {
           timer1.stop();
           MessageBox.Show("Dog #" + i + " wins!");
           foreach(Greyhound g in greyRay)
                g.TakeStartingPosition();
     }
}


Because what this piece of code is doing is running a loop through each of the dogs in the array, and running the run() method, which moves each one up a random amount...then only if it comes back true does it stop the timer, show the winner message box, and reset all the positions.

Hope this helps!



Hey, that did help, thanks for that. It didn't directly solve the problem but it definitely set me on the right track. The problem I have now is that all the dogs are moving the same distance each time. I've read about the clock usage for random so was thinking about adding a sleep unless you have a better idea?:

Greyhound.cs

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

namespace dugs
{
    public class Greyhound
    {
        public Point StartingPosition;
        public int RaceTrackLength;
        public PictureBox MyPictureBox;
        public int Location = 0;
        public Random Randomizer;
        public string name;

        public bool Run()
        {
            Randomizer = new Random();
            Location = StartingPosition.X;
            if (MyPictureBox.Location.X <= RaceTrackLength)
            {
                Point p = MyPictureBox.Location;
                int distance = Randomizer.Next(1, 5);
                p.X += distance;
                Location += distance;
                
                MyPictureBox.Location = p;
                //System.Threading.Thread.Sleep(50);
                System.Diagnostics.Debug.WriteLine("name" + name + "location: " + MyPictureBox.Location + " Distance: " + distance + " Length: " + RaceTrackLength + "start" + Location);
                return false;
            }
            return true;
            
    
        }

        public void TakeStartingPosition()
        {
            MyPictureBox.Location = StartingPosition;
        }

    }
}


Form1.cs

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 dugs
{
    public partial class form1 : Form
    {
        Greyhound g1;
        Greyhound g2;
        Greyhound g3;
        Greyhound g4;
        Greyhound[] greyRay;
        int minBet = 5;

        public form1()
        {
            InitializeComponent();
            minBet = 5;
            g1 = new Greyhound() { name = "Brutus1", StartingPosition = pictureBox2.Location, RaceTrackLength = (pictureBox1.Width - pictureBox2.Width -30), MyPictureBox = pictureBox2};
            g2 = new Greyhound() { name = "Rover2", StartingPosition = pictureBox3.Location, RaceTrackLength = (pictureBox1.Width - pictureBox2.Width- 30), MyPictureBox = pictureBox3 };
            g3 = new Greyhound() { name = "P3", StartingPosition = pictureBox4.Location, RaceTrackLength = (pictureBox1.Width - pictureBox2.Width- 30), MyPictureBox = pictureBox4 };
            g4 = new Greyhound() { name = "Cadger4", StartingPosition = pictureBox5.Location, RaceTrackLength = (pictureBox1.Width - pictureBox2.Width - 30), MyPictureBox = pictureBox5 };

            greyRay = new Greyhound[4];
            greyRay[0] = g1;
            greyRay[1] = g2;
            greyRay[2] = g3;
            greyRay[3] = g4;
        }
        

        private void button1_Click(object sender, EventArgs e)
        {
            timer1.Start();
        }

        private void menuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {

        }

        private void label1_Click(object sender, EventArgs e)
        {

        }

        private void pictureBox2_Click(object sender, EventArgs e)
        {

        }

        private void button3_Click(object sender, EventArgs e)
        {
            foreach (Greyhound g in greyRay)
            {
                g.TakeStartingPosition();
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            button1.Enabled = false;
            
            for(int i = 0; i < greyRay.Length; i++)
            {
                if (greyRay[i].Run() == true)
                {
                    timer1.Stop();
                    MessageBox.Show("Dog " + greyRay[i].name + " wins");
                    foreach(Greyhound g in greyRay){
                        g.TakeStartingPosition();
                    }
                    button1.Enabled = true;
   
                }
               // else{g
                
            }
        }
    }
}


Here is some logging I've been doing to debug:

nameBrutus1location: {X=92,Y=18} Distance: 2 Length: 569start83
nameRover2location: {X=94,Y=71} Distance: 2 Length: 569start83
nameP3location: {X=94,Y=133} Distance: 2 Length: 569start83
nameCadger4location: {X=94,Y=192} Distance: 2 Length: 569start83
nameBrutus1location: {X=94,Y=18} Distance: 2 Length: 569start83
nameRover2location: {X=96,Y=71} Distance: 2 Length: 569start83
nameP3location: {X=96,Y=133} Distance: 2 Length: 569start83
nameCadger4location: {X=96,Y=192} Distance: 2 Length: 569start83
nameBrutus1location: {X=96,Y=18} Distance: 2 Length: 569start83
nameRover2location: {X=98,Y=71} Distance: 2 Length: 569start83
nameP3location: {X=98,Y=133} Distance: 2 Length: 569start83
nameCadger4location: {X=98,Y=192} Distance: 2 Length: 569start83
nameBrutus1location: {X=100,Y=18} Distance: 4 Length: 569start85
nameRover2location: {X=102,Y=71} Distance: 4 Length: 569start85
nameP3location: {X=102,Y=133} Distance: 4 Length: 569start85
nameCadger4location: {X=102,Y=192} Distance: 4 Length: 569start85
nameBrutus1location: {X=103,Y=18} Distance: 3 Length: 569start84
nameRover2location: {X=105,Y=71} Distance: 3 Length: 569start84
nameP3location: {X=105,Y=133} Distance: 3 Length: 569start84
nameCadger4location: {X=105,Y=192} Distance: 3 Length: 569start84
nameBrutus1location: {X=106,Y=18} Distance: 3 Length: 569start84
nameRover2location: {X=108,Y=71} Distance: 3 Length: 569start84
nameP3location: {X=108,Y=133} Distance: 3 Length: 569start84
nameCadger4location: {X=108,Y=192} Distance: 3 Length: 569start84
nameBrutus1location: {X=109,Y=18} Distance: 3 Length: 569start84
nameRover2location: {X=111,Y=71} Distance: 3 Length: 569start84
nameP3location: {X=111,Y=133} Distance: 3 Length: 569start84
nameCadger4location: {X=111,Y=192} Distance: 3 Length: 569start

0

#6 User is offline   FrontalMonk 

  • New Member
  • Pip
  • Group: Members
  • Posts: 6
  • Joined: 15-January 14

Posted 16 January 2014 - 08:03 AM

yeah, I ran into that problem, too. I think the problem is with creating all four Random objects at basically the same time, the computer is giving all four the same seed for some crazy reason. The solution I went with was to create a Random object in the class, then instantiate it at runtime with the Random(int seed) constructor. Basically, when I create a new dog, I say this:

greyRay[0] = new Greyhound() { name = "Brutus1", Randomizer = new Random(1) };
//note the last item, with the int passed as a parameter for making a new Random


this helped make it so the dogs all moved at different rates, since I gave them all different random seeds (1, 2, 3, and 4). The problem with getting the seeds hardcoded is that they end up giving you the same results every time. If you ran this and dog #3 won the race the first time you run it, dog #3 will win the first race every time.

The alternative that I didn't actually get around to coding myself, but should do the trick, would be to create a random, then pull a random number there to set a seed for the dogs. So, like this:
Random dogSeed = new Random();

greyRay[0] = new Greyhound () { name = "Brutus1", Randomizer = new Random(dogSeed.Next(1,100)) };


and repeat for all 4 of your dogs. That way things will (hopefully) be a bit more randomized. I just really didn't have the patience to dig into it more.
0

#7 User is offline   wunderwaffe 

  • Active Member
  • PipPip
  • Group: Members
  • Posts: 26
  • Joined: 14-January 14

Posted 16 January 2014 - 08:59 AM

View PostFrontalMonk, on 16 January 2014 - 08:03 AM, said:

yeah, I ran into that problem, too. I think the problem is with creating all four Random objects at basically the same time, the computer is giving all four the same seed for some crazy reason. The solution I went with was to create a Random object in the class, then instantiate it at runtime with the Random(int seed) constructor. Basically, when I create a new dog, I say this:

greyRay[0] = new Greyhound() { name = "Brutus1", Randomizer = new Random(1) };
//note the last item, with the int passed as a parameter for making a new Random


this helped make it so the dogs all moved at different rates, since I gave them all different random seeds (1, 2, 3, and 4). The problem with getting the seeds hardcoded is that they end up giving you the same results every time. If you ran this and dog #3 won the race the first time you run it, dog #3 will win the first race every time.

The alternative that I didn't actually get around to coding myself, but should do the trick, would be to create a random, then pull a random number there to set a seed for the dogs. So, like this:
Random dogSeed = new Random();

greyRay[0] = new Greyhound () { name = "Brutus1", Randomizer = new Random(dogSeed.Next(1,100)) };


and repeat for all 4 of your dogs. That way things will (hopefully) be a bit more randomized. I just really didn't have the patience to dig into it more.


Cool solution, thanks a lot. Safer than a "sleep" anyway!

I'll struggling with some bet placing logic but I'll try for a bit longer.

Thanks again.
0

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users