生命游戏 | 信息学堂2025

114 阅读4分钟

ITI学院 2025.7

它一点也不难,耐心做完会很有意思。

Have fun!

生命游戏

什么是生命游戏?生命游戏是史上最著名的零玩家回合制游戏。当你摆好了游戏的初始状态,游戏就会自动进行下去,不需要玩家的参与。生命游戏通过二维网格来模拟若干“细胞”的生命活动,每个“细胞”根据周围8个格子的状态来计算下一回合的状态,其规则非常简单:

  1. 孤独和拥挤是致命的。如果一个“细胞”的“邻居”少于2个或多于3个,“细胞”就会死亡。
  2. 生命会繁衍。如果一个空格子周围的“细胞”恰好等于3个,那么下一回合这个格子就会变为“细胞”。

其他情况下,格子的生死会保持不变。

程序实现

在程序中,我们可以用二维数组来存储网格。定义一个二维数组field,我们用field[i][j] = 1来表示第ii行第jj列的格子有生命,用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(),让程序进入死循环,反复计算下一回合的状态并不断输出。注意:

  1. 你需要修改main()函数来添加新的指令,调用start()函数。你需要修改printMenu()函数来添加指令说明。
  2. 你可以在死循环中调用next()函数来计算下一回合的状态。
  3. 你可以在死循环中调用printField()函数来输出当前场上的状态。
  4. 你需要合理利用system("cls")Sleep(500),在恰当的地方清空屏幕或暂停,优化视觉效果。

任务四

好了!我们已经完成了最简单的生命游戏。下面,让我们休息一下,了解一下生命游戏究竟有什么样的意义。请观看下面的视频,注意保护膝盖:

www.bilibili.com/video/BV1Ey…

任务五

在上面视频中的01:20处,我们看到了非常小巧可爱的“滑翔机”结构。请你给程序添加一个新的命令glider,写一个新的函数glider(),读入两个整数i,ji, j,随后以第ii行第jj列的格子为“滑翔机”的左上角,在场地上生成一个“滑翔机”。注意:

  1. 你需要修改main()函数来添加新的指令,调用glider()函数。你需要修改printMenu()函数来添加指令说明。
  2. 使用命令形如:glider 10 20
  3. “滑翔机”的大小是3x3的,所以“滑翔机”的右下角在第i+2i+2行第j+2j+2
  4. 注意边缘情况。

任务六

如果你在空旷的地图上放下了一架“滑翔机”(任务五),并且启动了连续演算(任务三),你会发现它最终会“撞”在墙上。为了让它更有趣一点,我们决定改变场地的边界性质。

请修改next()函数,让最左边一列和最后边一列成为邻居,最上面一列和最下面一列也成为邻居。也就是,左侧出界从右边回来,上面出界从下面回来,这样每个格子周围都会有八个格子,不存在边界了。

提示:可以使用取模%来完成,特别注意四个角上的情况。

这样,我们的场地field在拓扑学上被改成了一个甜甜圈的表面。验证一下,我们的“滑翔机”可以永远在空旷的场地中飞行了!