康威的生命游戏规则
Conway's Game of Life Rules
我知道这有点含糊,但我一直在尝试在 JS 中实现康威生命游戏的规则,但我得到的结果是一团糟(不是正确的康威生命游戏框架)。谁能告诉我我执行规则有什么问题?
// Update state of selected cell
if ((neighbours < 2) && (cells[y][x].colour == "black")) {
// "Any live cell with fewer than two live neighbours dies, as if by underpopulation."
cells[y][x].colour = "white";
} else if ((2 <= neighbours <= 3) && (cells[y][x].colour == "black")) {
// "Any live cell with two or three live neighbours lives on to the next generation."
cells[y][x].colour = "black";
} else if ((neighbours == 3) && (cells[y][x].colour == "white")) {
// "Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction."
cells[y][x].colour = "black";
} else if ((3 < neighbours) && (cells[y][x].colour == "black")) {
// "Any live cell with more than three live neighbours dies, as if by overpopulation."
cells[y][x].colour = "white";
}
注意:我使用二维数组(矩阵)来存储游戏状态,每个单元格都被建模为一个简单的对象 - 这里唯一相关的参数是它的状态(存储为颜色,实时 "black").
您正在更新您阅读的同一个网格。您可能希望从拥有两个网格开始,即当前状态和新状态。遍历当前状态的单元格计算出新的状态,然后在下一次迭代中使用新的状态,依此类推。
您可以进行很多优化,但这会给您一个正确的起点。
此外,正如其他人指出的那样,习语 2 <= neighbours <= 3
不会像您认为的那样在 JS 中求值
您正在计算具有您正在变异的相同数据的邻居的数量。这样做的效果是一个单元格可以在 dead/alive 之间更改状态,然后该单元格的新数据可以用于另一个单元格的 "neighbors" 计算。
您需要两个网格副本才能正确完成。在计算新一代单元格时,必须使用上一代所有相邻单元格的值。但是你在循环期间覆盖了每个单元格,所以一些邻居将有他们的新值而不是旧值。
所以创建两个网格,一个叫current_cells
,另一个叫next_cells
。在计算新颜色应该是什么时使用 current_cells
,并将其分配给 next_cells[x][y].colour
。您还应该有一个 else
子句,它只复制
next_cells[x][y].colour = current_cells[x][y].colour;
在循环结束时,交换他们的角色:
[next_cells, current_cells] = [current_cells, next_cells];
我知道这有点含糊,但我一直在尝试在 JS 中实现康威生命游戏的规则,但我得到的结果是一团糟(不是正确的康威生命游戏框架)。谁能告诉我我执行规则有什么问题?
// Update state of selected cell
if ((neighbours < 2) && (cells[y][x].colour == "black")) {
// "Any live cell with fewer than two live neighbours dies, as if by underpopulation."
cells[y][x].colour = "white";
} else if ((2 <= neighbours <= 3) && (cells[y][x].colour == "black")) {
// "Any live cell with two or three live neighbours lives on to the next generation."
cells[y][x].colour = "black";
} else if ((neighbours == 3) && (cells[y][x].colour == "white")) {
// "Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction."
cells[y][x].colour = "black";
} else if ((3 < neighbours) && (cells[y][x].colour == "black")) {
// "Any live cell with more than three live neighbours dies, as if by overpopulation."
cells[y][x].colour = "white";
}
注意:我使用二维数组(矩阵)来存储游戏状态,每个单元格都被建模为一个简单的对象 - 这里唯一相关的参数是它的状态(存储为颜色,实时 "black").
您正在更新您阅读的同一个网格。您可能希望从拥有两个网格开始,即当前状态和新状态。遍历当前状态的单元格计算出新的状态,然后在下一次迭代中使用新的状态,依此类推。
您可以进行很多优化,但这会给您一个正确的起点。
此外,正如其他人指出的那样,习语 2 <= neighbours <= 3
不会像您认为的那样在 JS 中求值
您正在计算具有您正在变异的相同数据的邻居的数量。这样做的效果是一个单元格可以在 dead/alive 之间更改状态,然后该单元格的新数据可以用于另一个单元格的 "neighbors" 计算。
您需要两个网格副本才能正确完成。在计算新一代单元格时,必须使用上一代所有相邻单元格的值。但是你在循环期间覆盖了每个单元格,所以一些邻居将有他们的新值而不是旧值。
所以创建两个网格,一个叫current_cells
,另一个叫next_cells
。在计算新颜色应该是什么时使用 current_cells
,并将其分配给 next_cells[x][y].colour
。您还应该有一个 else
子句,它只复制
next_cells[x][y].colour = current_cells[x][y].colour;
在循环结束时,交换他们的角色:
[next_cells, current_cells] = [current_cells, next_cells];