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

Game of Life Neighbour Check (easier method possible?)

本文关键字:方法 更简单 游戏 邻居 检查 生活      更新时间:2023-10-16

我现在正试图用c++制作生活游戏,这是我有史以来的第一次c++练习。我有一个问题,我们需要制作一些游戏模式,比如一种被称为"圆环"的游戏模式,离开棋盘的细胞应该在相反的一侧重新进入棋盘。

现在,我正在检查邻居。但我用大量的if子句对它进行了硬编码,因为我尝试了一些for循环,但没有成功。

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

这是我的代码片段:

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;

}

我写了一个for循环,但并没有真正起作用,它是如下所示的——这个循环总是计算太多的单元格。循环后,所有细胞总是处于死亡状态,因为程序总是计数3个以上的活细胞,即使从一开始只有2个活细胞。我希望这个解释是有帮助的,它有点难以解释。我做了一个输出——"+"——它通常显示大约5/6个加号,即使它应该只显示两次(两个活细胞)。

// for any other "normal" cases inside of the board:
else if (a != 0 && b != 0 && a < HEIGHT - 1 && b < WIDTH - 1) {
for (int c = -1; c < 2; c++) {
for (int d = -1; d < 2; d++) {
if (!(c == 0 && d == 0)) {
if (board[a + c][b + d] != DEAD) {
living++; 
}
}
}
}
}

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

是。使用模数运算符:

代替

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

用途:

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

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

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

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

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

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

在执行这一行之前,您必须检查a + cb + d是否在矩阵范围内,以及它们是否不是应该执行的操作。对于"torus"需求,我认为超出范围的"left"answers"right"应该替换为换行值,超出范围的"top"answers"bottom"应该跳过。

除了Martin Bonner的答案外,还要准备八个邻居的偏移表:

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++;
}
}