C# 生命的游戏-这个算法是什么

C# 生命的游戏-这个算法是什么,c#,winforms,algorithm,C#,Winforms,Algorithm,我创造了一个简化的生活游戏 这是我的牢房,那里发生了真实的事情: class Cell { public Cell(MainWindow correspondingMainWindow){ this.mainWindow = correspondingMainWindow; } public bool excluded; public Boolean Occupied { get; set; } public Control corr

我创造了一个简化的生活游戏

这是我的牢房,那里发生了真实的事情:

class Cell
{
    public Cell(MainWindow correspondingMainWindow){
        this.mainWindow = correspondingMainWindow;
    }

    public bool excluded;

    public Boolean Occupied { get; set; }

    public Control correspondingPanel;

    private int[] coordinates;

    private MainWindow mainWindow;

    public int[] Coordinates
    {
        get { return this.coordinates; }
        set { 
            if(value.Length != 2) 
            {
                throw new ArgumentException();
            }
            else if(value[0] < 0 || value [1] < 0
                     || value[0] > Settings.FIELDWIDTH 
                     || value[1] > Settings.FIELDHEIGHT)
            {
                throw new ArgumentException();
            }
            else{
                correspondingPanel = mainWindow.FieldArea.Controls
                         .Find(String.Format("panel{0}_{1}", value[0], value[1]), true)
                         .FirstOrDefault();
                this.coordinates = value;
            }
        }

    }

    //Surrounding Cells in the 3x3 around the current cell
    //this is to speed up the updating as soon as the algorithm runs on many cells
    public Cell Top { get; set; }
    public Cell TopRight { get; set; }
    public Cell Right { get; set; }
    public Cell BotRight { get; set; }
    public Cell Bot { get; set; }
    public Cell BotLeft { get; set; }
    public Cell Left { get; set; }
    public Cell TopLeft { get; set; }

    public void die()
    {
        this.Occupied = false;
        this.correspondingPanel.BackColor = Color.Beige;
    }

    public void populate()
    {
        this.Occupied = true;
        this.correspondingPanel.BackColor = Color.DarkRed;
    }
}
每次算法完成运行所有单元格一次时,排除的和已运行的将重置为false。这是为了防止在此漫游中更新的单元格上调用walkOver()

现在,当我将单元格放在字段左上角(类似于简单的snake字段),标记它并运行算法时,它会在第一次运行后停止更改

它实际上以设计的方式更新单元格,但随后就停止了

我将我的单元格保存到程序中的一个静态列表中(我知道我不应该这样做,但在它正常工作之前,这是最简单的方法)。这些单元格有一些面板要匹配。这些面板位于名为FieldArea的组框中。它们是基于一些静态常量设置(您可以在坐标集验证中看到)动态生成的

我确信电池与面板正确匹配。这个问题似乎发生在从左上角(0,0)到右下角穿过FieldArea的对角线上。任何其他起点都可以正常工作。不知何故,当大量的细胞来自“顶部”时,这些细胞在场的顶部和左侧边缘形成一个边界


现在的问题是:我做错了什么?为什么我的字段不能正常工作?

您必须保留两份“世界”副本,因为在应用规则时,其中一份必须保持不变。如果将规则仅应用于一个世界,这将导致混合配置,其中一些单元格将具有旧状态,而其他单元格将已经具有新状态

因此,请这样做:

private Cell[,] activeWorld = new Cell[w,h];
private Cell[,] hiddenWorld = new Cell[w,h];

Populate(activeWorld);
while (true) {
    Display(activeWorld);
    ApplyRules(activeWorld, hiddenWorld);

    // Swap worlds
    var temp = activeWorld;
    activeWorld = hiddenWorld;
    hiddenWorld = temp;
}
方法
ApplyRules
必须从'activeWorld'读取单元格,并将结果写入
hiddenWorld


更新:在我看来,你的实际设计似乎有些过头了。一个简单的二维布尔数组告诉一个单元格是否被占用就足够了。不要从优化开始。这很可能会导致一个复杂的、难以阅读的错误代码。相反,将注意力集中在算法和良好的代码结构上。如果以后遇到性能问题,请分析问题并应用适当的优化。在>95%的情况下,问题与编码细节和算法无关,而是与I/O有关。在本游戏中,显示单元格可能比应用规则花费更多的时间。而且可能速度太快了,你必须在游戏循环中添加一个暂停

不要试图优化获取周围单元格索引的逻辑。不值得这么痛苦

解决边界单元问题的一个好方法是环视世界。使右侧看不见的东西重新出现在左侧,依此类推。为此使用模运算(%)<代码>x%N始终生成范围
0。。。N-1
。在给定x和y坐标的情况下,可以获得3 x 3单元格的坐标,如下所示:

for (int dx = -1; dx <= +1; dx++) {
    int i = (x + dx + Width) % Width;
    for (int dy = -1; dy <= +1; dy++) {
        int j = (y + dy + Height) % Height;
        bool occupied = world[i, j];
        ...
    }
}

for(int dx=-1;dx好的,正如我承诺的,这是我个人本周的胜利:

上述算法是“错误的”

不幸的是,我排除了没有改变的单元格。当我从“左上角”浏览列表时,错误出现了

我将排除移到die()和populate()函数

public void die(){
    this.Occupied = false;
    this.correspondingPanel.BackColor = Color.Beige;
    this.excluded = true;
}
然后,我还必须确保循环正确断开:

public Algorithm.walkOver(Cell target)
{
   if (target.Occupied && !target.excluded)
   {
       bool b = true;

   //if there could no changes be made, we also have to return there were no changes... 
   //else the while loop continues forever and we lose the process :(
       if (target.Right.Occupied && target.Left.Occupied 
           && target.Bot.Occupied && target.Top.Occupied)
       b = false;

       if(!target.Right.Occupied)
           target.Right.populate();

       if (!target.Left.Occupied)
           target.Left.populate();

       if (!target.Top.Occupied)
          target.Top.populate();

       if (!target.Bot.Occupied)
          target.Bot.populate();

       return b;
   }
   else
   {
      return false;
   }
}

我还将重置移动到while循环的开始,因为“选择”单元格会将其排除。

如果您的问题得到解决,请忘记我的评论。
public Algorithm.walkOver(Cell target)
{
   if (target.Occupied && !target.excluded)
   {
       bool b = true;

   //if there could no changes be made, we also have to return there were no changes... 
   //else the while loop continues forever and we lose the process :(
       if (target.Right.Occupied && target.Left.Occupied 
           && target.Bot.Occupied && target.Top.Occupied)
       b = false;

       if(!target.Right.Occupied)
           target.Right.populate();

       if (!target.Left.Occupied)
           target.Left.populate();

       if (!target.Top.Occupied)
          target.Top.populate();

       if (!target.Bot.Occupied)
          target.Bot.populate();

       return b;
   }
   else
   {
      return false;
   }
}