题目介绍:
康威生命游戏(Conway’s Game of Life),又称康威生命棋,是英国数学家约翰· 何顿·康威在 1970 年发明的细胞自动机。生命游戏模拟的是元胞内生命有机体的诞生与消亡的过程,其中元胞(Cell)被组织为格网(Grid)的形式。每个元胞要 么为空,或者包含了一个存活的有机体。包含有机体的元胞被称之为“存活的”,而空元胞则被称之为“死亡的”。
规则:
游戏开始时,每个细胞随机地设定为“生”或“死”之一的某个状态。然后,根据某种规则,计算出下一代每个细胞的状态,画出下一代细胞的生死分布图。
应该规定什么样的迭代规则呢?需要一个简单的,但又反映生命之间既协同又竞争的生存定律。为简单起见,最基本的考虑是假设每一个细胞都遵循完全一样的生存定律;再进一步,把细胞之间的相互影响只限制在最靠近该细胞的8个邻居中。
也就是说,每个细胞迭代后的状态由该细胞及周围8个细胞状态所决定。作了这些限制后,仍然还有很多方法来规定“生存定律”的具体细节。例如,在康威的生命游戏中,规定了如下生存定律。
(1)当前细胞为死亡状态时,当周围有3个存活细胞时,则迭代后该细胞变成存活状态(模拟繁殖);若原先为生,则保持不变。
(2)当前细胞为存活状态时,当周围的邻居细胞低于两个(不包含两个)存活时,该细胞变成死亡状态(模拟生命数量稀少)。
(3)当前细胞为存活状态时,当周围有两个或3个存活细胞时,该细胞保持原样。
(4)当前细胞为存活状态时,当周围有3个以上的存活细胞时,该细胞变成死亡状态(模拟生命数量过多)。
实现原理:二维数组/easyX/多线程
开发工具:Visual Studio 2022
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#include<graphics.h>
#define SPACE 10
#define ROWS 39
#define COLS 39
int drawEnd;
int startUp(int option);//开始,即显示菜单栏,并显示所能执行的操作
void drawRect(int x,int y,int flag);
void drawCells(int map[ROWS][COLS]);
void getAndset(int map[ROWS][COLS]);//读取鼠标的操作
void lifePeriod(int map[ROWS][COLS]); //生命周期,即细胞迭代的过程
int Cellsnum(int map[ROWS][COLS],int i,int j);//3×3格子内活细胞数量
int main()
{
drawEnd=true;
int option=0;
option=startUp(option);
initgraph(ROWS*SPACE,COLS*SPACE);//画布
int map[ROWS][COLS]= {0};//初始化数组
switch(option)
{
case 1:{
srand(time(NULL));
for (int i=0;i<ROWS;i++)
{
for (int j=0;j<COLS;j++)
{
map[i][j]=rand()%2;
drawCells(map);
}
}
}break;
case 2:{
CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)getAndset,(LPVOID)map,NULL,NULL);//为了让两个步骤同时进行
while(drawEnd)
{
BeginBatchDraw();
settextcolor(WHITE);
outtextxy(35*SPACE,37*SPACE,L"开始");
FlushBatchDraw();
drawCells(map);
Sleep(10);
}
EndBatchDraw();
settextcolor(WHITE);
outtextxy(1,1,L"人为细胞初始化结束,即将开始见证生命的演变。");
Sleep(1500);
break;}
case 3:{ //娱乐行为,还请谅解
int WechatID[ROWS][COLS]=
{
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,},//将微信二维码的小格当作细胞体
{0,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,0,0,0,0,1,0,0,0,0,1,1,0,0,1,1,1,1,1,1,1,0},
{0,1,0,0,0,0,0,1,0,1,0,0,1,1,0,1,1,1,0,1,0,0,1,1,0,0,0,0,0,1,0,1,0,0,0,0,0,1,0},
{0,1,0,1,1,1,0,1,0,0,0,1,1,0,1,0,1,0,0,1,1,0,0,1,1,1,1,0,0,1,0,1,0,1,1,1,0,1,0},
{0,1,0,1,1,1,0,1,0,1,0,1,1,0,1,1,0,0,1,0,0,1,0,1,1,1,1,0,1,1,0,1,0,1,1,1,0,1,0},
{0,1,0,1,1,1,0,1,0,0,1,1,0,1,0,1,1,1,0,0,1,0,0,1,0,1,1,1,1,1,0,1,0,1,1,1,0,1,0},
{0,1,0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,1,1,1,1,1,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0},
{0,1,1,1,1,1,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,1,1,1,1,0},
{0,0,0,0,0,0,0,0,0,1,0,0,1,1,0,1,0,1,0,0,0,1,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0},
{0,1,0,1,1,0,1,1,1,0,1,0,0,1,0,1,0,0,0,1,0,0,0,1,1,1,1,1,0,1,0,1,0,0,1,0,1,1,0},
{0,1,0,0,0,1,0,0,1,1,1,0,0,0,0,1,1,0,0,1,0,1,0,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0},
{0,1,0,1,1,1,1,1,1,0,0,0,1,0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,0,0,0,0,0,0,1,0,0,0},
{0,0,0,0,1,1,1,0,1,0,0,0,1,1,1,0,0,1,0,1,0,1,0,1,0,0,1,0,1,0,1,0,0,1,1,0,0,0,0},
{0,1,0,0,0,0,1,1,1,1,0,1,0,0,1,1,1,1,1,0,1,1,0,1,0,1,1,1,0,0,0,1,1,1,1,0,1,1,0},
{0,1,1,1,1,0,1,0,1,1,0,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1,0,1,0,0},
{0,0,1,0,1,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,1,0,1,0,0,0},
{0,1,1,0,0,1,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,1,1,0,1,1,0,1,1,1,1,0,0,0,1,0},
{0,0,1,0,0,1,0,1,1,1,0,1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,1,1,1,1,0,1,1,1,1,1,0,0},
{0,0,0,0,1,1,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,1,1,0,1,0,0,1,1,1,0},
{0,0,0,1,0,1,1,1,0,0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,1,1,1,0,1,1,1,0,1,0,0,0,1,1,0},
{0,0,1,0,0,0,1,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,1,0,1,0,0,1,0,0},
{0,1,1,0,0,1,0,1,0,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0,1,1,0,1,0,1,1,0,1,1,1,1,0,1,0},
{0,1,0,1,1,1,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,1,0,1,0,0,1,1,0,0,0,1,0,1,0,0},
{0,1,0,1,1,0,0,1,1,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,0,1,1,0,0,0,1,0,0},
{0,1,1,0,0,1,0,0,1,0,0,0,1,0,1,0,1,1,0,1,0,1,1,0,1,1,0,0,1,1,0,1,0,1,1,1,1,1,0},
{0,0,1,0,1,0,1,1,1,1,0,0,0,0,0,1,1,1,0,0,0,0,1,0,0,0,0,1,1,0,1,0,0,0,0,1,0,1,0},
{0,0,0,1,1,0,1,0,0,0,1,1,0,0,0,1,0,0,1,0,0,0,1,1,1,0,1,1,0,1,1,0,1,0,1,1,1,1,0},
{0,0,1,0,1,1,0,1,0,0,1,1,1,1,1,1,0,0,0,1,0,0,0,1,0,1,0,1,1,1,1,0,1,1,0,0,1,0,0},
{0,1,0,0,1,1,0,0,0,1,1,0,0,1,0,0,1,0,0,0,1,1,1,1,0,1,0,1,0,1,1,0,1,1,0,1,0,1,0},
{0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,1,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,0,0,0,1,0},
{0,0,0,0,0,0,0,0,0,1,0,0,1,1,0,1,1,0,0,1,1,1,1,0,0,1,1,0,0,1,0,0,0,1,01,0,1,0},
{0,1,1,1,1,1,1,1,0,1,0,1,1,0,1,0,1,1,0,1,0,0,0,1,0,0,0,0,0,1,0,1,0,1,0,1,1,1,0},
{0,1,0,0,0,0,0,1,0,1,1,0,0,1,1,1,1,0,1,1,1,0,1,0,0,1,0,0,1,1,0,0,0,1,0,0,1,1,0},
{0,1,0,1,1,1,0,1,0,0,1,0,1,1,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,1,1,1,1,0,1,0,0},
{0,1,0,1,1,1,0,1,0,1,0,1,1,0,1,1,1,1,1,0,0,0,1,0,0,0,1,1,0,0,1,1,0,1,1,0,0,0,0},
{0,1,0,1,1,1,0,1,0,1,1,1,0,0,0,1,1,0,1,0,0,0,1,1,0,0,0,0,1,0,1,1,0,1,1,0,1,0,0},
{0,1,0,0,0,0,0,1,0,0,0,1,1,1,1,1,1,0,0,1,1,0,0,0,1,1,1,1,1,1,0,0,1,1,0,1,0,0,0},
{0,1,1,1,1,1,1,1,0,1,1,1,1,0,1,1,0,1,1,1,0,0,0,1,1,1,1,0,1,0,1,1,0,1,0,0,1,1,0} };
memcpy(map,WechatID,sizeof(int)*ROWS*COLS);
drawCells(map);
Sleep(4000);
}
break;
}
while(1)//一直循环下去
{
lifePeriod(map);
drawCells(map);
Sleep(100);
}
return 0;
}
int startUp(int option)
{
printf("请");
do{
printf("输入所要执行的功能:\n");
printf(" 1、随机生成细胞分布(请按 1 )\n");
printf(" 2、手动控制细胞分布(请按 2 )\n");
printf(" 3、微信好友码型分布(请按 3 )\n");
scanf("%d",&option);
if(option>3)
printf("您输入的选项不在功能范围内,请重新");
}while(option>3);
return option;
}
void drawRect(int x,int y,int flag)
{
setcolor(RGB(167,167,167));
if(flag)
{
setfillcolor(WHITE);
}
else
{
setfillcolor(BLACK);
}
fillrectangle(x*SPACE,y*SPACE,x*SPACE+SPACE,y*SPACE+SPACE);
}
void drawCells(int map[ROWS][COLS])
{
for (int i=0;i<ROWS;i++)
{
for (int j=0;j<COLS;j++)
{
drawRect(j,i,map[i][j]);
}
}
}
void getAndset(int map[ROWS][COLS])
{
MOUSEMSG msg;
while(drawEnd)
{
msg=GetMouseMsg();
if(msg.mkLButton)
{
if((ROWS-2)==(msg.y/SPACE)&&(COLS-4)==(msg.x/SPACE)||
(ROWS-2)==(msg.y/SPACE)&&(COLS-3)==(msg.x/SPACE)||
(ROWS-2)==(msg.y/SPACE)&&(COLS-2)==(msg.x/SPACE)||
(ROWS-1)==(msg.y/SPACE)&&(COLS-4)==(msg.x/SPACE)||
(ROWS-1)==(msg.y/SPACE)&&(COLS-3)==(msg.x/SPACE)||
(ROWS-1)==(msg.y/SPACE)&&(COLS-2)==(msg.x/SPACE)
)//“开始”所在的区域范围
{
drawEnd=false;
}
map[msg.y/SPACE][msg.x/SPACE]=1;//左键点中的区域设为活细胞所在地
}
/*else
{
map[msg.y/SPACE][msg.x/SPACE]=0;
}*///第一次想的时候很符合思维逻辑,但实际上不需要,加上反而违法人的直觉
}
}
void lifePeriod(int map[ROWS][COLS])
{
int temp[ROWS][COLS]={0};
int sum;
for (int i=0;i<ROWS;i++)
{
for (int j=0;j<COLS;j++)
{
sum=Cellsnum(map,i,j);
if(sum==3)
{
temp[i][j]=1;
}
else if(sum==2)
{
temp[i][j]=map[i][j];
}
else
{
temp[i][j]=0;
}
}
}
/*for(int i=0;i<ROWS;i++)
{
for(int j=0;j<COLS;j++)
{
map[i][j]=temp[i][j];
}
}*/
//重复次数太多了
memcpy(map,temp,sizeof(int)*ROWS*COLS);
}
int Cellsnum(int map[ROWS][COLS],int i,int j)
{
int sum=0;
if(i>0&&j>0&&map[i-1][j-1])
sum++;
if(i>0&&map[i-1][j])
sum++;
if(i>0&&j<COLS-1&&map[i-1][j+1])
sum++;
if(j>0&&map[i][j-1])
sum++;
if (j<COLS-1&&map[i][j+1])
sum++;
if(i<ROWS-1&&j>0&&map[i+1][j-1])
sum++;
if(i<ROWS-1&&map[i+1][j])
sum++;
if(i<ROWS-1&&j<COLS-1&&map[i+1][j+1])
sum++;
return sum;
}