生命游戏(game of life)——初探二维元胞自动机

谨以此篇纪念John Conway。
今天在B站看了观视频的睡前消息,里面督公说的一个名叫“生命游戏”的自动机十分吸引我,加之他对该自动机进行了成功编译,故我准备试试。

规则很简单,具体请查看文末链接①,这里简单再说(这里的规则和督公所说的有出入,以百度为主):
1、细胞具有两种状态,生和死;
2、细胞的“周围”:与它相邻的八个细胞;
3、细胞的生死取决于周围细胞的生死,如果周围的活细胞等于2,则该细胞生死情况不变;如果周围的活细胞等于3,则该细胞存活;如果周围的细胞不是以上情况,则该细胞死亡。
4、对上述规则进行反复运用,最终形成细胞自动机。
确定了规则后,开始运用知识进行编程,首先主要到需要一个大矩阵,在开局声明

1
int a[101][101];

后,对矩阵进行初始化,该段代码略去。
之后该对矩阵的大小、初始细胞数量进行设定,这里利用随机数函数设定初始细胞数量,具体随机函数可以查看文末链接②,代码如下:

1
2
3
4
5
6
7
8
9
10
11
printf("输入方阵的行(列):\nN=");
int N;
scanf("%d",&N);
printf("输入细胞数:\n");
int n;
scanf("%d",&n);
srand(time(NULL));
for(int i = 0;i < n;i++)
{
a[rand()%11][rand()%11] = 1;
}

如果要运行该自动机,并且输出各个时刻的运行状态,则需要死循环语句(不要纠结不能退出了,我好久没打C了QAQ),

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
for(int i = 0;i < N;i++) //生命游戏规则主体 
{
for(int j = 0;j < N;j++)
{
int k = a[i][j];
int cnt = 0;
if(a[i-1][j-1] == 1) cnt++;
if(a[i-1][j] == 1) cnt++;
if(a[i-1][j+1] == 1) cnt++;
if(a[i][j-1] == 1) cnt++;
if(a[i][j+1] == 1) cnt++;
if(a[i+1][j-1] == 1) cnt++;
if(a[i+1][j] == 1) cnt++;
if(a[i+1][j+1] == 1) cnt++;
if(cnt == 2) a[i][j] = k;
if(cnt == 3) a[i][j] = 1;
if(cnt > 3 || cnt < 2) a[i][j] = 0;
cnt = 0;
}
}
(不要吐槽为什么有这么多if,因为我不会取巧TAT)

但是!如果只有此规则,那么各个时刻的运行状态只是一闪而过,此时要结合单片机的知识:加入延时函数!经测试,比较好观察的延时函数如下:

1
2
3
4
5
6
7
8
void delay(); //声明延迟函数 
...
void delay() //函数体
{
int t = 0;
while(t < 10000000) t++;
t = 0;
}

接下来考虑输出,运用传统二维数组的输出(for二层嵌套),考虑之前输入的矩阵大小输出,代码略。
最后运行,但是发现矩阵是一层一层叠下去的,不是一帧一帧闪过去的,于是百度,发现了清屏函数:

1
system("cls"); //该函数的头文件为stdlib.h,我还真不知道这个神奇的东西

编译并运行!
输出结果如下(取截屏,暂时不会录像,在考虑上传B站):
upload successful
写在最后:该理论的提出是John Conway,但是他在不久前去世了,做一个小程序,就当对大佬的缅怀吧。

附代码下载:
点击下载
点击下载

文末链接
①:https://baike.baidu.com/item/%E7%94%9F%E5%91%BD%E6%B8%B8%E6%88%8F/2926434?fr=aladdin
②:https://blog.csdn.net/knigh_yun/article/details/80082944