生命游戏邻居检查(更简单的方法可能吗?)

时间:2017-11-06 14:24:53

标签: c++

我正试图用c ++制作生活游戏,这是我有史以来的第一次C ++练习。我有一个问题,我们需要制作一些游戏模式,比如一个被称为“圆环”的游戏模式,其中离开棋盘的单元格应该在另一侧重新进入。

现在,我正在检查邻居。但我正在用很多if条款对它进行硬编码,因为我尝试了一些for循环,但它没有用。

但这真的是唯一的选择吗?硬编码每种可能性(左侧,右侧,上侧,下侧等的单元?

这是我的代码片段:

$Users = User::all();
    foreach ($Users as $User) {

        foreach ($userIDs as $user_id) {

            if ($user_id == $User->id) {
                echo '<br/>';
                echo $user_id;
                $User->has_rotas = 1;

            } else {
                $User->has_rotas = 0;
            }

        }
        $User->save();
    }

}

我写的一个for循环,但没有真正起作用,是以下 - 循环计数过多的单元格。在循环之后,所有细胞总是处于死亡状态,因为程序总是计数超过3个活细胞,即使从一开始只有2个细胞存活。我希望这个解释很有帮助,有点难以解释。我做了一个外印 - “+” - 它通常显示大约5/6加号,即使它只应显示两次(两个活细胞)。

int countNeighboursTorus(int a, int b) {

int living = 0;

// when the starting cell is the one on the upper left (start of the board)
if (a == 0 && b == 0) {

    // cell below
    if (board[a - 1][b] != DEAD) {
        living++;
    }
    // cell right below
    if (board[a + 1][b + 1] != DEAD) {
        living++;
    }
    // cell right
    if (board[a][b + 1] != DEAD) {
        living++;
    }
    // cell above (other side of the board)
    if (board[HEIGHT - 1][b] != DEAD) {
        living++;
    }
    // cell above right (other side of the board)
    if (board[HEIGHT - 1][b + 1] != DEAD) {
        living++;
    }

}

// first edge case (height = 0, width != 0):
else if (a == 0 && b != 0) {
    // cell below
    if (board[a - 1][b] != DEAD) {
        living++;
    }
    // cell right below
    if (board[a + 1][b + 1] != DEAD) {
        living++;
    }
    // cell right
    if (board[a][b + 1] != DEAD) {
        living++;
    }
    // cell left below
    if (board[a + 1][b - 1] != DEAD) {
        living++;
    }
    // cell left
    if (board[a][b - 1] != DEAD) {
        living++;
    }
    // cell left above (other side of the board)
    if (board[HEIGHT - 1][b - 1] != DEAD) {
        living++;
    }
    // cell above (other side of the board)
    if (board[HEIGHT - 1][b] != DEAD) {
        living++;
    }
    // cell above right (other side of the board)
    if (board[HEIGHT - 1][b + 1] != DEAD) {
        living++;
    }
}

return living;

有没有可以简化的选项?比如循环,就像我试过的那样?或者这是应该做的方式?我现在真的没有看到隧道尽头的光。只是为了让我知道我是否一无所获。我真的遇到了一些C ++语法的问题,因为到目前为止我只用了大约一年的Java,所以我是C ++的初学者。我很感激任何提示!

3 个答案:

答案 0 :(得分:5)

是。使用模数运算符:

而不是

    if (board[a + 1][b + 1] != DEAD) {

使用:

    if (board[(a + 1) % HEIGHT][(b + 1) % WIDTH] != DEAD) {

进行减法时有一点点复杂性(%实际上不是模数运算,它是余数运算)。你不想在-1上使用它(它只会返回-1),所以添加一个额外的HEIGHT / WIDTH:

    if (board[(a - 1 + HEIGHT) % HEIGHT][(b - 1 + WIDTH) % WIDTH] != DEAD) {

然后,您可以对电路板的所有单元使用相同的代码。

答案 1 :(得分:1)

此行尝试访问不在矩阵范围内的矩阵元素:

if (board[a + c][b + d] != DEAD) {

在执行此行之前,您必须检查a + cb + d是否在矩阵范围内,如果它们不是应该执行的操作。对于“圆环”要求,我猜“左”和“右”超出范围应该用换行值替换,并且应该跳过超出范围的“顶部”和“底部”。

答案 2 :(得分:1)

除了Martin Bonner's answer之外,准备八个邻居的抵消表:

static const int NoOfNeighbors = 8;

int  dVertNeigh [NoOfNeighbors] = {
    HEIGHT-1, HEIGHT-1, HEIGHT-1,
    0,                  0,
    1,        1,        1};

int  dHorizNeigh [NoOfNeighbors] = {
    WIDTH-1,  0,        1,
    WIDTH-1,            1,
    WIDTH-1,  0,        1};

然后你可以通过一个简单的循环计算邻居单元格:

for (int ngh = 0; ngh < NoOfNeighbors; ngh++) {
    int neighborV = (a + dVertNeigh[ngh]) % HEIGHT;
    int neighborH = (b + dHorizNeigh[ngh]) % WIDTH;

    if (board[neighborV][neighborH] != DEAD) {
        living++;
    }
}