我已经完成了生命游戏的实现,但在应用游戏规则后渲染网格时遇到了问题。我有一个看起来像这样的游戏循环:
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应该看到。游戏规则应该逐个细胞地应用,以便它的某些方面:将游戏规则应用于单元格,绘制网格,将游戏规则应用于另一个单元格,绘制网格......?
答案 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;
}
}