C语言生命游戏操作步骤与源码(easyX版)

作者:袖梨 2026-08-08

C语言生命游戏操作步骤与源码(easyX版)并不只看表面做法,关键还要理解相关条件、限制和后续影响。

一、项目介绍

这是我曾经在某个科普书上看到过的内容。在那本书当中有一个关于世界本源的讨论,即我们目前发现的物理定律,是否可能是更基础的模块的宏观呈现?因此,那本书提到了这个游戏,即设定一个简单的世界法则,以及对应的初始条件,然后观察它的演化,看看是否能呈现出某种更复杂的东西。

这个世界的法则十分简单。所有物质分为活细胞和死细胞,分别表示为绿色以及灰黑色。如果上一刻,一个活细胞周围8格的活细胞多余3个或少于2个,那么它就会死去;如果一个死细胞周围恰好有3个活细胞,那么就会在此诞生一个新的活细胞。设定了这样的法则之后,我们就可以观察这个世界的演化了。

编译环境:visual c++ 6.0

第三方库:Easyx2022 注意需要提前安装easyX,如没有基础可以先了解easyX图形编程

二、运行截图

img_6a7675b49b2e530.webp

img_6a7675b49b2ec31.webp

三、源码解析

程序的整体逻辑十分简单。

初始化;

然后开始循环;

如果按下1-9,调节游戏速度;

如果按下s,产生一个方形分布世界,重新开始;

如果按下r,产生一个随机分布世界,重新开始;

进行一回合的演化,绘制图像;

睡眠一定时间,继续循环;

游戏结束。

变量和函数也不多:

// 定义全局变量__int8 world[102][102] = {0};          // 定义二维世界IMAGE imgLive, imgEmpty;              // 定义活细胞和无细胞区域的图案  // 函数声明void Init();                                             // 初始化void SquareWorld();                           // 创建一个细胞以方形分布的世界void RandWorld();                              // 创建一个细胞随机分布的世界void PaintWorld();                              // 绘制世界void Evolution();                                  // 进化

接下来我们看每个函数的实行:

// 初始化void Init(){         // 创建绘图窗口         initgraph(640,480);          // 设置随机种子         srand((unsigned)time(NULL));          // 调整世界图案的大小         Resize(&imgLive,  4, 4);         Resize(&imgEmpty, 4, 4);          // 绘制有生命世界的图案         SetWorkingImage(&imgLive);         setcolor(GREEN);         setfillstyle(GREEN);         fillellipse(0, 0, 3, 3);          // 绘制无生命世界的图案         SetWorkingImage(&imgEmpty);         setcolor(DARKGRAY);         rectangle(1, 1, 2, 2);          // 恢复对默认窗口的绘图         SetWorkingImage(NULL);          // 输出简单说明         setfont(24, 0, "黑体");         outtextxy(254, 18, "生 命 游 戏");         RECT r = {440, 60, 620, 460};         setfont(12, 0, "宋体");         drawtext("生命游戏简介:n,                  &r, DT_WORDBREAK);          // 产生默认的细胞以方形分布的世界         SquareWorld();}

initgraph用于初始化绘图窗口。在头文件Easyx当中,后面的函数如果没有说明,默认也是在Easyx当中的。

Resize用于调整指定绘图设备的尺寸,避免绘制图像过大。

然后绘制有生命的图案和无生命的图案,其原理类似:

SetWorkingImage用于设定当前的绘图设备,将数据写入对应地址位置。

setcolor用于设置绘图前景色,setfillstyle用于设置当前设备填充样式。

fillellipse这个函数用于画有边框的填充椭圆。

接下来输出说明:

setfont设置字体

outtextxy用于在特定位置输出文字

RECT r用于为drawtext设定一个指定矩形区域的指针

drawtext这个函数用于在指定区域内以指定格式输出字符串。

然后是两个创建世界的函数。

// 创建一个细胞以方形分布的世界void SquareWorld(){       memset(world, 0, 102 * 102 * sizeof(__int8));        for(int x = 1; x <= 100; x++)              world[x][1] = world[x][100] = 1;        for(int y = 1; y <= 100; y++)              world[1][y] = world[100][y] = 1;}// 创建一个细胞随机分布的世界void RandWorld(){       for(int x = 1; x <= 100; x++)              for(int y = 1; y <= 100; y++)                     world[x][y] = rand() % 2;}

利用二层循环遍历world[x][y]当中每个数据,将其调整到想要的值。随机世界将每个细胞的状态设置为随机数除以2的余数,保证每次产生的都是新的世界。

然后是绘制世界图像。

// 绘制世界void PaintWorld(){       for(int x = 1; x <= 100; x++)              for(int y = 1; y <= 100; y++)                     putimage(16 + x * 4, 56 + y * 4, world[x][y] ? &imgLive : &imgEmpty);}

利用双层循环,将每个点的状态所对应图像打印出来。

最后是世界的演化函数,从世界的当前状态推出世界下一刻。

// 进化void Evolution(){       __int8 tmp[102][102] = {0};        // 临时数组       int sum;        for(int x = 1; x <= 100; x++)       {              for(int y = 1; y <= 100; y++)              {                     // 计算周围活着的生命数量                     sum = world[x+1][y] + world[x+1][y-1] + world[x][y-1] + world[x-1][y-1]                            + world[x-1][y] + world[x-1][y+1] + world[x][y+1] + world[x+1][y+1];                      // 计算当前位置的生命状态                     switch(sum)                     {                            case 3:           tmp[x][y] = 1;                      break;                            case 2:           tmp[x][y] = world[x][y];        break;                            default:   tmp[x][y] = 0;                      break;                     }              }       }        // 将临时数组恢复为世界       memcpy(world, tmp, 102 * 102 * sizeof(__int8));}

我们只需要定义一个临时数组,根据当前的世界状态推断就可以了。计算某个坐标周围8格活着的生命数量,得出该点的状态。注意数组的边界。

之后用memcpy将临时数据输入world变量当中。

memcpy是<string.h>当中的内存拷贝函数,可用于复制任何种类的数据。

// 主函数int main(){       Init();       int Speed = 500;                // 游戏速度(毫秒)        while(true)       {              if (kbhit() || Speed == 900)              {                     char c = getch();                      if (c == ' ' && Speed != 900)                            c = getch();                      if (c >= '0' && c <= '9')                            Speed = ('9' - c) * 100;                      switch(c)                     {                            case 's':                            case 'S':                                   SquareWorld();      // 产生默认的细胞以方形分布的世界                                   break;                             case 'r':                            case 'R':                                   RandWorld(); // 产生默认的细胞随机分布的世界                                   break;                             case VK_ESCAPE:                                   goto END;                     }              }               Evolution();                  // 进化              PaintWorld();                // 绘制世界               if (Speed != 900)         // 速度为 900 时,为按任意键单步执行                     Sleep(Speed);       } END:       closegraph();       return 0;}

最后放一个主函数。

函数 kbhit()函数的作用是检查控制台窗口的按键是否被按下。

closegraph()用于关闭绘图区域。

四、完整源码

生命游戏C语言完整源码

相关文章

精彩推荐