C 人生游戏问题

标签 c conways-game-of-life

我正在尝试用 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() 中的主循环无法在各代之间交替。您可以保留我建议的更改,并删除对 printCurrentFieldprintNextField 的所有引用。这可以让您简化函数 printField()

关于C 人生游戏问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40096856/

相关文章:

C 二维数组结构比较问题

c - ANSI C 中的复合语句( block )是否被括号表达式包围?

c - 根据字长打印直方图 (C)

c - 奇怪的 C 函数 - 这个函数在做什么?

c++ - 如何在已弃用的函数中添加字符串或消息

modeling - 用整数线性规划模拟康威的生命游戏?

c - 在单元测试过程代码时删除依赖项

javascript - 如何遍历由二维数组表示的板上单元格的所有邻居?

java - 生命游戏,方法行不通

java - 生命游戏 - 蟾蜍模式的输入