康威游戏的生活渲染
本文关键字:的生活 游戏 康威 | 更新日期: 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;
}
}