康威游戏的生活渲染

本文关键字:的生活 游戏 康威 | 更新日期: 2023-09-27 17:51:03

我已经完成了一款生活游戏的实现,但在应用游戏规则后渲染网格时遇到了一个问题。我有一个像这样的游戏循环:

while (gameIsRunning)
{
    //Needed for accessing UIControls from the background
    //thread.
    if (InvokeRequired)
    {
        //Process the array.
        MainBoard.Cells = engine.ApplyGameRules(MainBoard.Cells, MainBoard.Size.Height, MainBoard.Size.Width, BOARD_DIMENSIONS);
        //Check if there is a state such as
        //all states being dead, or all states being
        //alive.
        //Update the grid with the updated cells.
        this.Invoke(new MethodInvoker(delegate
                                     {
                                         timeCounter++;
                                         lblTimeState.Text = timeCounter.ToString();
                                         pictureBox1.Invalidate();
                                         pictureBox1.Update();
                                         Thread.Sleep(100);
                                     }));
        }
    }

和如下的绘制函数:

for (int x = 0; x < MainBoard.Size.Height; x++)
{
    for (int y = 0; y < MainBoard.Size.Width; y++)
    {
        Cell individualCell = MainBoard.Cells[y, x];
        if (individualCell.IsAlive() == false)
        {
            e.Graphics.FillRectangle(Brushes.Red, MainBoard.Cells[y, x].Bounds);
        }
        //White indicates that cells are alive
        else if (individualCell.IsAlive() == true)
        {
            e.Graphics.FillRectangle(Brushes.White, MainBoard.Cells[y, x].Bounds);
        }
        else if (individualCell.IsInfected() == true)
        {
            e.Graphics.FillRectangle(Brushes.Green, MainBoard.Cells[y, x].Bounds);
        }
        //Draws the grid background itself.
        e.Graphics.DrawRectangle(Pens.Black, MainBoard.Cells[y, x].Bounds);
    }
}

我遇到的问题是,我将所有游戏规则应用于网格中的每个细胞,然后绘制网格,然后再次应用所有规则,所以我永远不会得到我应该看到的生命形式的斑点。游戏规则是否应该在每个细胞的基础上应用,这样就像:将游戏规则应用于细胞,绘制网格,将游戏规则应用于另一个细胞,绘制网格……

康威游戏的生活渲染

看起来程序当前的意图是正确的。

你应该做的是(伪代码):

  Board oldBoard = new Board(start cell definitions);
  while(not finished) {
      Board newBoard = calculate(oldBoard);
      display(newBoard);
      oldBoard = newBoard();
  }

如果你没有看到你想要的表单,那么要么你的显示代码是错误的,要么你的规则代码是错误的。

在伪代码中,我扔掉了上一代的板,一旦它不再需要,并为每一代制作一个新的板。calculate()包含new Board()语句

当然,如果制作一个新板很贵,你可以重复使用一个,只是在"当前"answers"其他"板之间来回切换。只要记住,每次你写入一个板,它的新状态必须100%是上一代状态的函数,并且不受它自己的起始状态的影响。也就是说,你必须写入每个单元格。

另一种方法是每个单元格保存两个值。所以你有一个板,每个单元格包含一个"当前"answers"以前"的值,而不是两个板,每个单元格一个值。

  Board board = new Board(initial state);
  while(not finished) {
      board.calculate(); // fills "current" cells based on "previous" cells.
      display(board);
      board.tick(); // "current" becomes "previous".
                    // "previous" becomes current, but is "dirty" until calculated.
  }

有很多方法可以做到这一点。一种方法是:

  public class Cell {
      private boolean[] state = new boolean[2];
      private int generation = 0;
      public void setCurrentState(boolean state) {
          state[generation] = state;
      }
      public void getCurrentState() {
          return state[generation];
      }
      public void getLastState() {
          return state[ (generation + 1) % 2 ];
      }
      public void tick() {
          generation = (generation + 1) % 2;
      }
  }