C语言实现康威生命游戏
2024-04-22 23:00:45

引子

某个假期,在看《黑客》这本书时,看到以前MIT的黑客很喜欢玩这个游戏。规则看起来不是很复杂,就试着实现一下吧。

生命游戏中,对于任意细胞,规则如下:

  • 每个细胞有两种状态 - 存活或死亡,每个细胞与以自身为中心的周围八格细胞产生互动(如图,黑色为存活,白色为死亡)
  • 当前细胞为存活状态时,当周围的存活细胞低于2个时(不包含2个),该细胞变成死亡状态。(模拟生命数量稀少)
  • 当前细胞为存活状态时,当周围有2个或3个存活细胞时,该细胞保持原样。
  • 当前细胞为存活状态时,当周围有超过3个存活细胞时,该细胞变成死亡状态。(模拟生命数量过多)
  • 当前细胞为死亡状态时,当周围有3个存活细胞时,该细胞变成存活状态。(模拟繁殖)

可以把最初的细胞结构定义为种子,当所有在种子中的细胞同时被以上规则处理后,可以得到第一代细胞图。按规则继续处理当前的细胞图,可以得到下一代的细胞图,周而复始。

1. 主体逻辑实现

主体的逻辑实现不难,用两个布尔类型的二维数组表示新、旧地图,根据旧地图,计算出新地图中每一个cell的状态即可。

对于一个cell来说,首先根据旧地图,获取其存活的邻居数量:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int getNeighbor(int x, int y, bool oldMatrix[BOARD_HEIGHT][BOARD_WIDTH]) {
int result = 0;

for(int xCord = x - 1; xCord <= x + 1; xCord++) {
if(xCord < 0 || xCord >= BOARD_HEIGHT) continue;

for(int yCord = y - 1; yCord <= y + 1; yCord++) {
if(yCord < 0 || yCord >= BOARD_WIDTH) continue;

if(!(xCord == x && yCord == y)) {
if(oldMatrix[xCord][yCord]) {
result++;
}
}
}
}

return result;
}

然后根据自身的状态和邻居的个数,获取其将要变成什么状态:

1
2
3
4
5
6
7
8
9
10
11
12
13
bool getStatus(int neighbor, bool originalStatus) {
if(originalStatus) {
if(neighbor == 2 || neighbor == 3) {
return true;
}
}
else {
if(neighbor == 3) {
return true;
}
}
return false;
}

在主函数中,设置两个二维数组matrix1matrix2,在主循环中,先将matrix1看作旧地图,将matrix2看作新地图,遍历地图上每一个点,在更新完一次地图之后,再把matrix2看作旧地图,matrix1看作新地图,周而复始,删减的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 while(1) {
for(int i = 0; i < BOARD_HEIGHT; i++) {
for(int j = 0; j < BOARD_WIDTH; j++) {
neighbor = getNeighbor(i, j, matrix1);
matrix2[i][j] = getStatus(neighbor, matrix1[i][j]);
neighbor = 0;
}
}

outputMatrix(matrix2);

for(int i = 0; i < BOARD_HEIGHT; i++) {
for(int j = 0; j < BOARD_WIDTH; j++) {
neighbor = getNeighbor(i, j, matrix2);
matrix1[i][j] = getStatus(neighbor, matrix2[i][j]);
neighbor = 0;
}
}

outputMatrix(matrix1);

}

2. 一些不重要的细节

最开始的地图可以通过一个文件来读取,也可以随机地生成一些存活的cell。

Prev
2024-04-22 23:00:45
Next