蚁群执行过程中在winforms中动态绘制蚂蚁
Dynamic drawing ants in winforms during execution of ant colony
在针对我在 c# 中的个人蚁群项目提出这个问题 () 之后,我正在尝试应用第二个建议的解决方案:将轨迹绘制成位图和新蚂蚁相结合的解决方案到表面上。
[...]Application.Run(new ShowAnts());[...]
public partial class ShowAnts : Form
{
Bitmap bmp;
int j = 0;
public ShowAnts()
{
InitializeAntProgram();
InitializeComponent();
bmp = new Bitmap(pictureBox1.ClientSize.Width, pictureBox1.ClientSize.Height);
pictureBox1.Image = bmp;
}
public void RenderAnts(object sender, PaintEventArgs e)
{
using (Graphics G = Graphics.FromImage(pictureBox1.Image))
{
while (j < 1000)
{
Map.EvaporatesPheromones();
foreach (Vector2D food in foodSrcs)
{
Map.SetMapPoint(food, 500);
}
foreach (Ant a in ants)
{
Brush c;
c = Brushes.DarkBlue;
if (a.role == AntRole.Scout)
{
a.Move(j);
c = Brushes.Red;
}
e.Graphics.FillRectangle(Brushes.DarkBlue, a.position.x, a.position.y, 1, 1);
G.FillRectangle(Brushes.Gray, a.position.x, a.position.y, 1, 1);
}
j++;
}
}
}
}
上面的代码显示了将蚂蚁运动绘制到 winform 中的图形尝试。
它工作完美,但它只显示最终结果。我想展示一步一步的演变,在不重新分析我的地图信息的情况下保持图形轨迹信息。
请考虑我正在开发此 "graphic interface" 的工作控制台项目已经存在,因此:
- 一些变量在项目的其他地方设置(即:食物);
- `a.Move(j);`指的是蚂蚁逻辑本身(分析、决策、引用地图数组的新单元格移动);
- `j` 计数器用于计算步数和设置任意停止,但没有实际用途;
- 我已经将所有关于信息素、运动、位置等的信息存储到地图数组和一些其他变量中
查看您的代码以及上一个问题的评论,您似乎遗漏了可以为运动设置动画的部分。相反,您在似乎是 Paint
事件的内部循环。
这里有一个快速解决方法。它添加了一个触发 RenderAnts
事件的 Timer
,该事件似乎连接到 pictureBox1.Paint
处理程序..:[=27=]
几个class级变量:
int counter = 0;
int limit = 1000;
Timer antTimer = new Timer();
起始码:
antTimer.Interval = 50; // <-- pick your speed !!
antTimer.Tick += (ss, ee) =>
{ pictureBox1.Invalidate(); counter++; if (counter > limit) antTimer.Stop(); };
antTimer.Start();
速度为50ms,即每秒20Ticks
Tick
事件内嵌了一个微小的 Lambda
表达式,只有一个语句加上循环逻辑。通过 Invalidating
pictureBox1
控制其 Paint
事件,从而触发 RenderAnts
事件。
另请注意,我将其称为 'quick fix'。通常您会区分动画的渲染和移动代码;但在这种情况下,这种细微差别并不重要。
现在我们改一下RenderAnts
方法,去掉循环:
public void RenderAnts(object sender, PaintEventArgs e)
{
using (Graphics G = Graphics.FromImage(pictureBox1.Image))
{
Map.EvaporatesPheromones();
foreach (Vector2D food in foodSrcs)
{
Map.SetMapPoint(food, 500);
}
foreach (Ant a in ants)
{
Brush c = Brushes.DarkBlue;
if (a.role == AntRole.Scout)
{
a.Move(j);
c = Brushes.Red;
}
e.Graphics.FillRectangle(c, a.position.x, a.position.y, 1, 1);
G.FillRectangle(Brushes.Gray, a.position.x, a.position.y, 1, 1);
}
}
}
您可能还想添加一个 Start/Stop Button
。还有一个TrackBar
来改变速度..
现在您应该能够以 20Hz 的频率观察蚂蚁的行进,留下灰色痕迹。
在针对我在 c# 中的个人蚁群项目提出这个问题 (
[...]Application.Run(new ShowAnts());[...]
public partial class ShowAnts : Form
{
Bitmap bmp;
int j = 0;
public ShowAnts()
{
InitializeAntProgram();
InitializeComponent();
bmp = new Bitmap(pictureBox1.ClientSize.Width, pictureBox1.ClientSize.Height);
pictureBox1.Image = bmp;
}
public void RenderAnts(object sender, PaintEventArgs e)
{
using (Graphics G = Graphics.FromImage(pictureBox1.Image))
{
while (j < 1000)
{
Map.EvaporatesPheromones();
foreach (Vector2D food in foodSrcs)
{
Map.SetMapPoint(food, 500);
}
foreach (Ant a in ants)
{
Brush c;
c = Brushes.DarkBlue;
if (a.role == AntRole.Scout)
{
a.Move(j);
c = Brushes.Red;
}
e.Graphics.FillRectangle(Brushes.DarkBlue, a.position.x, a.position.y, 1, 1);
G.FillRectangle(Brushes.Gray, a.position.x, a.position.y, 1, 1);
}
j++;
}
}
}
}
上面的代码显示了将蚂蚁运动绘制到 winform 中的图形尝试。 它工作完美,但它只显示最终结果。我想展示一步一步的演变,在不重新分析我的地图信息的情况下保持图形轨迹信息。
请考虑我正在开发此 "graphic interface" 的工作控制台项目已经存在,因此:
- 一些变量在项目的其他地方设置(即:食物);
- `a.Move(j);`指的是蚂蚁逻辑本身(分析、决策、引用地图数组的新单元格移动);
- `j` 计数器用于计算步数和设置任意停止,但没有实际用途;
- 我已经将所有关于信息素、运动、位置等的信息存储到地图数组和一些其他变量中
查看您的代码以及上一个问题的评论,您似乎遗漏了可以为运动设置动画的部分。相反,您在似乎是 Paint
事件的内部循环。
这里有一个快速解决方法。它添加了一个触发 RenderAnts
事件的 Timer
,该事件似乎连接到 pictureBox1.Paint
处理程序..:[=27=]
几个class级变量:
int counter = 0;
int limit = 1000;
Timer antTimer = new Timer();
起始码:
antTimer.Interval = 50; // <-- pick your speed !!
antTimer.Tick += (ss, ee) =>
{ pictureBox1.Invalidate(); counter++; if (counter > limit) antTimer.Stop(); };
antTimer.Start();
速度为50ms,即每秒20Ticks
Tick
事件内嵌了一个微小的 Lambda
表达式,只有一个语句加上循环逻辑。通过 Invalidating
pictureBox1
控制其 Paint
事件,从而触发 RenderAnts
事件。
另请注意,我将其称为 'quick fix'。通常您会区分动画的渲染和移动代码;但在这种情况下,这种细微差别并不重要。
现在我们改一下RenderAnts
方法,去掉循环:
public void RenderAnts(object sender, PaintEventArgs e)
{
using (Graphics G = Graphics.FromImage(pictureBox1.Image))
{
Map.EvaporatesPheromones();
foreach (Vector2D food in foodSrcs)
{
Map.SetMapPoint(food, 500);
}
foreach (Ant a in ants)
{
Brush c = Brushes.DarkBlue;
if (a.role == AntRole.Scout)
{
a.Move(j);
c = Brushes.Red;
}
e.Graphics.FillRectangle(c, a.position.x, a.position.y, 1, 1);
G.FillRectangle(Brushes.Gray, a.position.x, a.position.y, 1, 1);
}
}
}
您可能还想添加一个 Start/Stop Button
。还有一个TrackBar
来改变速度..
现在您应该能够以 20Hz 的频率观察蚂蚁的行进,留下灰色痕迹。