Conways Game of Life渲染

时间:2014-03-20 14:17:21

标签: c# conways-game-of-life

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

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);
    }
}

我遇到的问题是我将所有游戏规则应用于网格中的每个单元格,然后绘制该网格,然后再次应用所有规则,以便我永远不会获得生命形式blob应该看到。游戏规则应该逐个细胞地应用,以便它的某些方面:将游戏规则应用于单元格,绘制网格,将游戏规则应用于另一个单元格,绘制网格......?

1 个答案:

答案 0 :(得分:1)

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

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

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

如果您没有看到预期的表单,那么您的显示代码是错误的,或者您的规则代码是错误的。

在伪代码中,一旦不再需要,我就会抛弃上一代的电路板,为每一代制作一块新电路板。 calculate()包含new Board()声明。

当然,如果制作一块新电路板很昂贵,你可以重新使用一块电路板,只需在“当前”和“其他”电路板之间来回切换。请记住,每次写入电路板时,其新状态必须是上一代状态的100%,并且不受其自身起始状态的影响。即你必须写信给每个小区。

另一种方法是每个单元格保存两个值。因此,不是每个单元具有一个值的两个板,而是每个单元包含一个“当前”和“前一个”值的单板。

  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;
      }

  }