【数学&编程】C++实现康威生命游戏

【数学&编程】C++实现康威生命游戏

康威生命游戏

康威生命游戏(Game of Life)是由剑桥大学约翰·何顿·康威设计的计算机程序,图灵完备(Turing Completeness),是细胞自动机的先驱。
在这里插入图片描述

康威生命游戏规则

游戏开始时,每个细胞随机地设定为“生”或“死”之一的某个状态。然后,根据某种规则,计算出下一代每个细胞的状态,画出下一代细胞的生死分布图。
应该规定什么样的迭代规则呢?需要一个简单的,但又反映生命之间既协同又竞争的生存定律。为简单起见,最基本的考虑是假设每一个细胞都遵循完全一样的生存定律;再进一步,把细胞之间的相互影响只限制在最靠近该细胞的8个邻居中。
也就是说,每个细胞迭代后的状态由该细胞及周围8个细胞状态所决定。作了这些限制后,仍然还有很多方法来规定“生存定律”的具体细节。例如,在康威的生命游戏中,规定了如下生存定律。
(1)当前细胞为死亡状态时,当周围有3个存活细胞时,则迭代后该细胞变成存活状态(模拟繁殖);若原先为生,则保持不变。
(2)当前细胞为存活状态时,当周围的邻居细胞低于两个(不包含两个)存活时,该细胞变成死亡状态(模拟生命数量稀少)。
(3)当前细胞为存活状态时,当周围有两个或3个存活细胞时,该细胞保持原样。
(4)当前细胞为存活状态时,当周围有3个以上的存活细胞时,该细胞变成死亡状态(模拟生命数量过多)。
可以把最初的细胞结构定义为种子,当所有种子细胞按以上规则处理后,可以得到第1代细胞图。按规则继续处理当前的细胞图,可以得到下一代的细胞图,周而复始。
上面的生存定律当然可以任意改动,发明出不同的“生命游戏”。

C++实现


/*
代码由 CSDN 千鱼干原创,转载请注明出处
*/

#include <iostream>
#include <windows.h>
#include <cstring>
#include <string.h>
#include <ctime>

using namespace std;

/*
   注意:h (高)和 w (宽)需要根据控制台设置
   使得生命状态图边界不超过控制台长宽。否则显示会出问题
*/

const int h = 55;
const int w = 95;

const string live = " ■";
/*
   存活生命用实心方块表示,注意:
   本程序运行于 Windows 11 的 Windows Terminal下
   故方块前加了个空格以使显示效果整齐
*/

const string die = "  ";     // 死亡状态

// 设置当前生命状态图 surface 和下一新生命状态图 new_surface
int surface[h][w], new_surface[h][w];

// 设置生命状态图填充内容
void putVal(int val){
    for(int i = 0; i < h; i++){
        for(int j = 0; j < w; j++){
            surface[i][j] = val;
            new_surface[h][w] = val;
        }
    }
}

// 清空生命状态图
void clearSurface(){
    putVal(0);
}

// 填满生命状态图
void fullSurface(){
    putVal(1);
}

// 设置输出游标,只针对被修改的地方 (x, y) 输出
void updatePos(int x, int y) {
	COORD pos = {y * 2, x};
	HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleCursorPosition(hOut, pos);
	printf("%s", (surface[x][y] != 0) ? live.c_str() : die.c_str());
}


// 展示生命状态图
void showSurface(){
    for(int i = 0; i < h; i++){
        for(int j = 0; j < w; j++){
            printf("%s", (surface[i][j] != 0) ? live.c_str() : die.c_str());
        }
        printf("\n");
    }
}

// 随机生成生命状态图,p 为初始存活概率
void randomSeed(int p){
    clearSurface();
    // 设置随机数种子
    srand((unsigned int)time(NULL));
    for(int i = 0; i < h; i++){
        for(int j = 0; j < w; j++){
            if((rand() % 100) <= p){
                surface[i][j] = 1;
                new_surface[h][w] = 1;
            }
        }
    }
}

// 判断 (x, y) 附近的生命数量
int pdAround(int x, int y){
    int x_sub = (x + h - 1) % h;
    int y_sub = (y + w - 1) % w;
    int x_plus = (x + 1) % h;
    int y_plus = (y + 1) % w;
    int lifes = (
                (surface[x_sub][y_sub] == 1)
              + (surface[x_sub][y] == 1)
              + (surface[x_sub][y_plus] == 1)
              + (surface[x][y_plus] == 1)
              + (surface[x_plus][y_plus] == 1)
              + (surface[x_plus][y] == 1)
              + (surface[x_plus][y_sub] == 1)
              + (surface[x][y_sub] == 1)
                );
    return lifes;
}

// 设置位于 (x, y) 处生命的状态
void setState(int x, int y){
    // 如果无生命
    if(surface[x][y] == 0){
        // 当周围生命数量为 3 时产生新生命(模拟繁殖)
        if(pdAround(x, y) == 3){
            new_surface[x][y] = 1;
            return;
        }
    }else{
        // 如果已存在生命,当周围生命数量低于 2 或大于 3 死亡,分别模拟生命数量稀少和生命数量过多
        if((pdAround(x, y) < 2) || (pdAround(x, y) > 3)){
            new_surface[x][y] = 0;
            return;
        }
    }
}

// 刷新当前生命状态图为新生命状态图
void refreshSurface(){
    for(int i = 0; i < h; i++){
        for(int j = 0; j < w; j++){
            if(surface[i][j] != new_surface[i][j]){
                surface[i][j] = new_surface[i][j];
                updatePos(i, j);
            }
        }
    }
}

// 一次生命状态图模拟
void fun(){
    for(int i = 0; i < h; i++){
        for(int j = 0; j < w; j++){
            setState(i, j);
        }
    }
    refreshSurface();
}

int main() {
    int p = 80;
    cout << "输入初始存活概率(0~100,建议不要过高):___\b\b\b";
    cin >> p;
    system("cls");
    system("color f0");
    clearSurface();  // 清空生命状态图
    randomSeed(p);    // 随机产生生命状态图
    showSurface();   // 输出初始生命状态图
    Sleep(1000);
    int j = 100;
    while(true){
        fun();          // 一次生命状态图模拟
    }
    return 0;
}

实现效果

在这里插入图片描述
在这里插入图片描述

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值