想知道为什么我的代码需要一个等待计时器,因为一切都应该运行串行,没有它的重大无意义的更改



我的目标是创建100个点并让它们采用随机路径,这是一个简单的进化算法。但是,它需要一个等待计时器来使每个点的路径唯一,从我对代码的测试和查看来看,我认为没有理由发生这种情况。我可以保持原样,但我喜欢理解我编写的代码。因为没有任何特定的错误或任何东西,不幸的是,我确实必须提供相当多的代码(大约 200 行带有空格和注释),我讨厌这样做,但它真的只是必要的文件。 他们应该得到很好的评论,所以我希望这至少有所帮助,很抱歉不方便

using System;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing;
using System.Workflow.ComponentModel;
class Genetics
{
//Just a bunch of references to classes
//----------------------------------------
Dot.Class dot = new Dot.Class();
FormSetup setup = new FormSetup();
Brain.Class brain = new Brain.Class();
Watch watch = new Watch();
Population.Class Pop = new Population.Class();
Dot.Class[] Dots;
//----------------------------------------
//The main function just starts a timer, and sets up the form in FormSetup and runs the application

private static void Main(string[] args)
{
Genetics gen = new Genetics();
gen.watch.watch();
FormSetup.Start();
}

//Makes the dots before anything visual occurs
public void Form1_Load(object sender, EventArgs e)
{
Dots = Pop.Birth();
}
//Paint sets up the goal and draws and redraws the dots by following their location
//This does not fire before the birthing process is done
public void Paint(object sender, PaintEventArgs e)
{

Goal.Class goal = new Goal.Class();
Graphics G = e.Graphics;
Pen pen = new Pen(Color.Black);
//------------------------------------
//Goal
G.DrawRectangle(pen, goal.MakeGoal());
//Since this should fire as many times as tick, which fires every 50th milisecond, it should follow the dots and drawing spheres from their locations pretty alright
//Goes through the list from the birth process (Dots) and initiates the Move() method for each of them, which sets their path coordinates randomly. 
// This path SHOULD be unique to every single on of them, but without a wait timer, they aren't.
for (int i = 0; i < Dots.Length; i++)
{
Dots[i].Move();
G.DrawEllipse(pen, Dots[i].Location.X, Dots[i].Location.Y, 10, 10);
// With that testing loop, I saw how that without the sleep function, every dot had the same path, however with it, each dot's path is unique.
/* for (int b = 0; b < Dots[i].Directions.Length; b++)
{
Console.WriteLine("I am dot number: " + i + " And for step number: " + b + " my coordinate is: " + Dots[i].Directions[b]);
} */
}



}
//This just asks the form to be redrawn every 50th milisecond. This event does not fire before the Birthing process is complete.
public void Tick(object sender, EventArgs e)
{
FormSetup.form1.Invalidate();
FormSetup.form1.Update();
}

}

上面的代码是主代码,最可能的原因是 paint 方法中的 for 循环

下面是大脑代码,对我来说更奇怪,评论中有更多解释,但它根本不应该受到等待计时器的影响,但唉,确实如此。

using System;
using System.Windows;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing;
using System.Workflow.ComponentModel;
namespace Brain
{
//The Brain program makes a big array of directions, and then randomizes a whole path of them
public class Class
{
// Sets up the variables
Point[] Directions;
Random rand = new Random();
//The GetDirections methods sets the size of the point array, then runs the randomize method, then returns the directions
public Point[] GetDirections(int size)
{
Directions = new Point[size];
Randomize();
return Directions;
}
// Simply fills the entire Directions point array with randonmized points
//This will output the same path over and over without the sleep function, however that doesn't make too much sense for me, since this is only called a bit AFTER the sleep function, since this method is only called after load, which stores all the dots
void Randomize()
{
for (int i = 0; i < Directions.Length; i++)
{
Directions[i] = new Point(rand.Next(-5, 5), rand.Next(-5, 5));

}
}
}
}

然后是创建很多点的种群代码,这是实际诞生点集合的代码,并且还包含睡眠函数

using System;
using System.Windows;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing;
using System.Workflow.ComponentModel;
namespace Population
{
public class Class
{
//Makes a variable for the dots array
Dot.Class[] dots;
//Birth is only called once just before the form is loaded
public Dot.Class[] Birth()
{
//Sets the size of the dots array
dots = new Dot.Class[100];
//Fills out the dots array with unique Dot classes
for (int i = 0; i < dots.Length; i++)
{
dots[i] = new Dot.Class();
//This little thing that the code requires for it to semi-work, and I have no idea why...
System.Threading.Thread.Sleep(50);

}
return dots;
}
}
}

所以,正如你现在已经注意到的那样,重点是每个点都有一个唯一的坐标路径,但由于某种原因,如果没有 for 循环的每次迭代之间的睡眠函数,它就不会这样做,如果它在它之外,它不会做任何事情。 我在这里严重迷失了方向,因为我不知道我的代码在这里做什么,虽然我是表单的新手,但这似乎不是表单问题,因为问题是纯坐标,而不是它们在屏幕上的显示方式。

我将非常感谢任何想要尝试和帮助的人。

添加了点代码:

public class Class
{
//Creates relevant variables for the dots
public Point Location = new Point(1370/2, 650/2);
Point Velocity = new Point(0, 0);
Point accelleration = new Point(0, 0);
bool IsDead = false;
int DistanceToGoal = 0;
public Point[] Directions;
//Some more variables, these are just used for some cheap programming tricks
bool StartupComplete = false;
int steps = 0;
//Class references
public Brain.Class brain = new Brain.Class();
Goal.Class goal = new Goal.Class();

//This is called every 50th milisecond after the load of the form. Before this Method is called, the dot won't have any coordinates
public void Move()
{
//A one-off if statement that fills the Directions array with the randomized points from the brain
if (!StartupComplete)
{
Directions = brain.GetDirections(500);
StartupComplete = true;
}
//Will only move if not marked as death
if (!IsDead)
{
//Makes sure that we aren't going further into the array than allowed to. We do not use a for loop here, because it is called every 50th milisecond
if (steps < Directions.Length)
{
//Just fills the accelleration variable with the randomized directions relevant to the current step, and then goes to the next step for the next itteration
accelleration.X = Directions[steps].X;
accelleration.Y = Directions[steps].Y;
steps++;
}
//If there are no more directions, the dot is marked as death
else
{
IsDead = true;
}
//Sets and limits the velocity
Velocity.Y += accelleration.Y;
if (Velocity.Y > 10)
Velocity.Y = 10;
if (Velocity.Y < -10)
Velocity.Y = -10;
Velocity.X += accelleration.X;
if (Velocity.X > 10)
Velocity.X = 10;
if (Velocity.X < -10)
Velocity.X = -10;
//Moves an amount equal to the velocity, then checks if the dot is out of bounds
Location.X += Velocity.X;
Location.Y += Velocity.Y;
CheckDead();

}
}
//Just checks if the dot is just about halfway outside the form size
void CheckDead()
{
if (Location.X > 1374 || Location.X < -0.4)
IsDead = true;
if (Location.Y > 654 || Location.Y < -0.4)
IsDead = true;


}

我只能猜测,但这看起来像是Random()的问题,因为它使用时钟生成随机数。它也可以解释为什么Thread.Sleep(50)可以帮助您使用随机路径。

基本上,在一个紧密的循环中,你会得到很多次相同的值。我敢打赌这就是这里发生的事情。您应该保留单个Random实例,并在同一实例上继续使用Next

尝试更改随机发生器以使用以下代码:

private static readonly Random random = new Random(); 
private static readonly object syncLock = new object(); 
public static int RandomNumber(int min, int max)
{
lock(syncLock) { // synchronize
return random.Next(min, max);
}
}

我希望它有所帮助 😊

最新更新