我正在尝试用 C 语言编写生命游戏。我已经坐了 7 个小时想知道如何解决它。我已经走了很远,但有些东西使代码无法正常工作。我相信我在结构中的下一个变量和当前变量之间做错了。计算邻居是死是活可能是错误的。无论如何,我将不胜感激任何帮助!
void checkField(const int rows, const int cols, cell field[rows][cols]) {
int neighborCount;
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
neighborCount = getNeighborCount(rows, cols, r, c, field);
nextGeneration(rows, cols, r, c, neighborCount, field);
}
}
}
int getNeighborCount(const int rows, const int cols,
int r, int c, cell field[rows][cols]) {
int neighborCount = 0;
neighborCount += checkNeighbors(rows, cols, r - 1, c - 1, field);
neighborCount += checkNeighbors(rows, cols, r - 1, c, field);
neighborCount += checkNeighbors(rows, cols, r - 1, c + 1, field);
neighborCount += checkNeighbors(rows, cols, r, c - 1, field);
neighborCount += checkNeighbors(rows, cols, r, c + 1, field);
neighborCount += checkNeighbors(rows, cols, r + 1, c - 1, field);
neighborCount += checkNeighbors(rows, cols, r + 1, c, field);
neighborCount += checkNeighbors(rows, cols, r + 1, c + 1, field);
return neighborCount;
}
int checkNeighbors(const int rows, const int cols,
int r, int c, cell field[rows][cols]) {
int neighborAlive;
if (r < 0 || r > rows || c < 0 || c > cols || field[r][c].current != ALIVE){
return neighborAlive = 0;
}
else {
return neighborAlive = 1;
}
}
void nextGeneration(const int rows, const int cols,
int r, int c, int neighborCount, cell field[rows][cols]) {
for (int r = 0 ; r < rows ; r++) {
for (int c = 0 ; c < cols ; c++) {
field[r][c].current = DEAD;
field[r][c].next = DEAD;
}
}
if (neighborCount < 2){
field[r][c].current = DEAD;
field[r][c].next = DEAD;
}
if (neighborCount == 2 || neighborCount == 3) {
field[r][c].current = ALIVE;
field[r][c].next = ALIVE;
}
if ((field[r][c].current == DEAD) && neighborCount == 3) {
field[r][c].current = ALIVE;
field[r][c].next = ALIVE;
}
if (neighborCount >= 4) {
field[r][c].current = DEAD;
field[r][c].next = DEAD;
}
}
最佳答案
既然 checkNeighbors()
函数中的条件已经生效,那么从一代更新到下一代的方式会遇到一些问题。在函数 nextGeneration()
中,您不需要清除单元格数组,因为无论如何您都将覆盖下一代。在此函数中的每个测试中,您都有,例如:
if (neighborCount < 2){
field[r][c].current = DEAD;
field[r][c].next = DEAD;
}
但你只需要field[r][c].next = DEAD;
。这是您的新 nextGeneration()
函数:
void nextGeneration(const int rows, const int cols,
int r, int c, int neighborCount, cell field[rows][cols]) {
if (neighborCount < 2)
field[r][c].next = DEAD;
if (neighborCount == 2 || neighborCount == 3)
field[r][c].next = ALIVE;
if ((field[r][c].current == DEAD) && neighborCount == 3)
field[r][c].next = ALIVE;
if (neighborCount >= 4)
field[r][c].next = DEAD;
}
然后,在checkField()
函数的末尾,您需要将下一代复制到当前一代中。这是您的新 checkField()
函数:
void checkField(const int rows, const int cols, cell field[rows][cols]) {
int neighborCount;
int r, c;
for (r = 0; r < rows; r++) {
for (c = 0; c < cols; c++) {
neighborCount = getNeighborCount(rows, cols, r, c, field);
nextGeneration(rows, cols, r, c, neighborCount, field);
}
}
/* Now, copy next generation into current */
for (r = 0; r < rows; r++)
for (c = 0; c < cols; c++)
field[r][c].current = field[r][c].next;
}
通过这些更改,您的代码对我有用,尽管我认为您的规则可能存在问题。我尝试了滑翔机,但它的行为并不符合我的预期。这是第二代网格的样子:
. . X . . . . . . . . . . . . . . . . .
X . X X . . . . . . . . . . . . . . . .
. X X X . . . . . . . . . . . . . . . .
X X X . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
剧透警告:
这是一个更新的 nextGeneration()
函数,其中包含正确实现康威生命游戏的规则。你最初的规则是再生只有 2 个邻居的死亡细胞。
void nextGeneration(const int rows, const int cols,
int r, int c, int neighborCount, cell field[rows][cols]) {
if (field[r][c].current == ALIVE) {
if ((neighborCount < 2) || (neighborCount > 3)){
field[r][c].next = DEAD;
} else {
field[r][c].next = ALIVE;
}
} else {
if (neighborCount == 3) {
field[r][c].next = ALIVE;
} else {
field[r][c].next = DEAD;
}
}
}
更新:
完成上述所有操作后,我现在看到您试图在当前和下一代之间来回翻转显示。这使更新逻辑变得复杂,因为您也必须在此处进行代之间的交替。最重要的是,这段代码比它需要的更复杂。您可以按照您想要的方式实现此目的,但仍然存在许多导致问题的更新问题,并且 main()
中的主循环无法在各代之间交替。您可以保留我建议的更改,并删除对 printCurrentField
和 printNextField
的所有引用。这可以让您简化函数 printField()
。
关于C 人生游戏问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40096856/