ITI学院 2025.7
它一点也不难,耐心做完会很有意思。
Have fun!
生命游戏
什么是生命游戏?生命游戏是史上最著名的零玩家回合制游戏。当你摆好了游戏的初始状态,游戏就会自动进行下去,不需要玩家的参与。生命游戏通过二维网格来模拟若干“细胞”的生命活动,每个“细胞”根据周围8个格子的状态来计算下一回合的状态,其规则非常简单:
- 孤独和拥挤是致命的。如果一个“细胞”的“邻居”少于2个或多于3个,“细胞”就会死亡。
- 生命会繁衍。如果一个空格子周围的“细胞”恰好等于3个,那么下一回合这个格子就会变为“细胞”。
其他情况下,格子的生死会保持不变。
程序实现
在程序中,我们可以用二维数组来存储网格。定义一个二维数组field,我们用field[i][j] = 1来表示第行第列的格子有生命,用field[i][j] = 0表示这个格子为空。
不用担心,我已经帮你写了一部分代码了,但仍有一些任务需要你来完成。你可以在这里找到一部分残缺的代码:
// XXXT2025 Game of Life
#include <Windows.h>
#include<bits/stdc++.h>
using namespace std;
const int H = 40, W = 120;
int field[H][W];
void printField() {
cout << "请你完成这个部分!" << endl;
}
void printMenu() {
cout << endl << "请最大化窗口,在此输入命令,支持的命令有:" << endl;
cout << "random 随机生成生命" << endl;
cout << "next 演算下一回合" << endl;
cout << "> ";
}
void random() { // random 0, 1
for (int i = 0; i < H; i++) {
for (int j = 0; j < W; j++) field[i][j] = rand() % 2;
}
}
void next() {
cout << "请你完成这个部分!" << endl;
}
int main() {
// initialize
for (int i = 0; i < H; i++) {
for (int j = 0; j < W; j++) field[i][j] = 0;
}
while(1) {
system("cls"); // clear screen
printField();
printMenu();
string s;
cin >> s;
if (s == "random") random();
if (s == "next") next();
Sleep(500); // stop for 0.5 seconds
}
return 0;
}
请在这份代码上修改,并完成下面的任务。
任务一
可以看到,在上面的代码当中,printField()函数是不完整的。请你帮我补全这里的代码,将当前的field数组输出到控制台上。
如果一个格子有生命,则输出O,否则输出.。别忘了转行噢!
任务二
现在你已经可以看到生命游戏场上的状态了!尝试运行程序,输入命令random并回车,程序就会随机生成一些生命。
现在,你需要完成next()函数,根据生命游戏的规则,计算出下一回合每个格子的状态,并将新的状态存入field数组。
你可以用next命令来调试next()函数。别忘了边缘情况噢!
任务三(选做)
现在,你需要一个更自动的方式来观察生命的演化过程。请你给程序加一个新的命令start,写一个新的函数start(),让程序进入死循环,反复计算下一回合的状态并不断输出。注意:
- 你需要修改
main()函数来添加新的指令,调用start()函数。你需要修改printMenu()函数来添加指令说明。 - 你可以在死循环中调用
next()函数来计算下一回合的状态。 - 你可以在死循环中调用
printField()函数来输出当前场上的状态。 - 你需要合理利用
system("cls")和Sleep(500),在恰当的地方清空屏幕或暂停,优化视觉效果。
任务四
好了!我们已经完成了最简单的生命游戏。下面,让我们休息一下,了解一下生命游戏究竟有什么样的意义。请观看下面的视频,注意保护膝盖:
任务五
在上面视频中的01:20处,我们看到了非常小巧可爱的“滑翔机”结构。请你给程序添加一个新的命令glider,写一个新的函数glider(),读入两个整数,随后以第行第列的格子为“滑翔机”的左上角,在场地上生成一个“滑翔机”。注意:
- 你需要修改
main()函数来添加新的指令,调用glider()函数。你需要修改printMenu()函数来添加指令说明。 - 使用命令形如:
glider 10 20 - “滑翔机”的大小是3x3的,所以“滑翔机”的右下角在第行第列
- 注意边缘情况。
任务六
如果你在空旷的地图上放下了一架“滑翔机”(任务五),并且启动了连续演算(任务三),你会发现它最终会“撞”在墙上。为了让它更有趣一点,我们决定改变场地的边界性质。
请修改next()函数,让最左边一列和最后边一列成为邻居,最上面一列和最下面一列也成为邻居。也就是,左侧出界从右边回来,上面出界从下面回来,这样每个格子周围都会有八个格子,不存在边界了。
提示:可以使用取模%来完成,特别注意四个角上的情况。
这样,我们的场地。验证一下,我们的“滑翔机”可以永远在空旷的场地中飞行了!field在拓扑学上被改成了一个甜甜圈的表面