Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# c“来自”的新问题;领先C“灰狗实验室”;_C# - Fatal编程技术网

C# c“来自”的新问题;领先C“灰狗实验室”;

C# c“来自”的新问题;领先C“灰狗实验室”;,c#,C#,我是C#的新手,我正在创建一个赛道模拟器,但我目前在运行代码时遇到了一些问题。我有一个由四个灰狗对象组成的数组,如果我在form1.cs上调用Greyhound.Run,我的Run方法中没有“MessageBox.Show(“Distance”+Distance)”,它告诉我每只灰狗应该移动多少像素,那么所有的灰狗最终都会移动相同的距离。我不明白为什么会这样 namespace Race { class Greyhound { public int Startin

我是C#的新手,我正在创建一个赛道模拟器,但我目前在运行代码时遇到了一些问题。我有一个由四个灰狗对象组成的数组,如果我在form1.cs上调用Greyhound.Run,我的Run方法中没有“MessageBox.Show(“Distance”+Distance)”,它告诉我每只灰狗应该移动多少像素,那么所有的灰狗最终都会移动相同的距离。我不明白为什么会这样

namespace Race
{
    class Greyhound
    {
        public int StartingPosition;
        public int RacetrackLength;
        public PictureBox MyPictureBox = null;
        public int Location = 0;
        public Random Randomizer;

        public bool Run()
        {
            Point p = MyPictureBox.Location;
            if (p.X + MyPictureBox.Width >= RacetrackLength)
            {
                //TakeStartingPostion();
                return true;

            }
            else
            {
                Randomizer = new Random();
                int distance = Randomizer.Next(100);
                MessageBox.Show("Distance is " + distance);
                p.X += distance;
                MyPictureBox.Location = p;
                return false;
            }

        }

        public void TakeStartingPostion()
        {
            Point P = MyPictureBox.Location;
            P.X = StartingPosition;
            MyPictureBox.Location = P;
        }
    }
}


namespace Race
{
    public partial class Form1 : Form
    {
        Guy[] guys = new Guy[3];
        Greyhound[] hounds = new Greyhound[4];

        public Form1()
        {
            InitializeComponent();

            hounds[0] = new Greyhound()
            { 
                StartingPosition = 12,
                MyPictureBox = GreyHound1,
                RacetrackLength = 636
            };

            hounds[1] = new Greyhound()
            { 
                StartingPosition = 12,
                MyPictureBox = GreyHound2,
                RacetrackLength = 636
            };

            hounds[2] = new Greyhound()
            { 
                StartingPosition = 12,
                MyPictureBox = GreyHound3,
                RacetrackLength = 636
            };

            hounds[3] = new Greyhound()
            { 
                StartingPosition = 12,
                MyPictureBox = GreyHound4,
                RacetrackLength = 636
            };
        }

        private void button2_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < hounds.Length; i++)
            {

                 hounds[i].Run();
            } 

        }
    }
}
命名空间竞争
{
灰狗级
{
公共int启动位置;
公共跑道长度;
公共PictureBox MyPictureBox=null;
公共int位置=0;
公共随机随机化器;
公营学校
{
点p=MyPictureBox.位置;
如果(p.X+MyPictureBox.Width>=跑道长度)
{
//takestartingposition();
返回true;
}
其他的
{
随机发生器=新随机();
int距离=随机发生器。下一步(100);
MessageBox.Show(“距离为”+距离);
p、 X+=距离;
MyPictureBox.Location=p;
返回false;
}
}
公开作废开始公告()
{
点P=MyPictureBox.位置;
P.X=启动位置;
MyPictureBox.Location=P;
}
}
}
名称空间竞赛
{
公共部分类Form1:Form
{
Guy[]guys=新人[3];
灰狗[]猎犬=新灰狗[4];
公共表格1()
{
初始化组件();
猎犬[0]=新灰狗()
{ 
启动位置=12,
MyPictureBox=灰狗1,
跑道长度=636
};
猎犬[1]=新灰狗()
{ 
启动位置=12,
MyPictureBox=灰狗2,
跑道长度=636
};
猎犬[2]=新灰狗()
{ 
启动位置=12,
MyPictureBox=灰狗3,
跑道长度=636
};
猎犬[3]=新灰狗()
{ 
启动位置=12,
MyPictureBox=灰狗4,
跑道长度=636
};
}
私有无效按钮2\u单击(对象发送者,事件参数e)
{
for(int i=0;i
这是因为每次
Run()
方法点击
else
块时,您都在调用
new Random()
。默认的
Random
构造函数基于当前时间初始化伪随机数生成器。当没有中断时,所有4个方法“同时”运行,所以它们吐出相同的随机数。要解决此问题,请仅创建一个
Random
,或者为每个种子使用不同的种子(通过使用将种子作为参数的
Random
构造函数)

类似这样的方法会奏效:

public class Greyhound
{
    public static Random randomizer = new Random();

    // ... In the run method ...
    int distance = Greyhound.randomizer.Next(100);

}
Update:正如Groo指出的,如果您实际上是从多个线程调用
Next()
,那么我显示的代码不是线程安全的。虽然您的代码并非如此,但最好尽早意识到此类问题,而不是晚些时候。此(潜在)问题的一般解决方案是使用
锁围绕对
Next()
的调用,如下所示:

// ... After the declaration of randomizer ...
private static object randomLock = new object();

// ... New Next() call...
lock (randomLock)
    Greyhound.randomizer.Next(100);

由于您可能会连续快速地调用所有对象的
Run
方法,因此
Random
类的每个实例都会实例化,并返回相同的伪随机数

您可以通过创建一个静态随机类来解决此问题,该类将有一个(单例)
random
实例,确保每个调用者都连续获得下一个号码

通过一些线程安全锁定,它看起来像:

 public class StaticRandom 
 {
      private static readonly Random _r = new Random();
      private static object _lock = new object();

      public static int Next(int max)
      {
           lock (_lock)
               return _r.Next(max);
      }
 }
然后在不实例化的情况下使用它:

 // no need for the "Randomizer" field anymore
 int distance = StaticRandom.Next(100);

Jon Skeet在他的miscutil库中有完整的实现,还有一些。

@Alfonso,@dlev:这个例子是。您应该锁定对
Next
方法的每次调用。这就是为什么创建自己的静态随机类更简单,它将自己进行锁定。@Groo我知道,但它不是线程安全的,这无关紧要:OP只使用一个线程(因为最初的代码段都是从for循环运行的,而当前的代码段是基于按钮点击运行的,这都是从UI线程运行的。)不过,总的来说,您当然是正确的;我将添加一个更新来提及这个问题。