The game of life(生命游戏)新算法

时间:2023-03-09 15:05:41
The game of life(生命游戏)新算法

我写了一种常见的实现算法,和另一种新算法,即不是每次循环计算每个细胞的周围细胞数来产生下一时刻,而是每次每个产生状态变化的细胞主动通知周围的邻居,因此每个细胞增加一个用来记录邻居数的字段。由邻居数决定每个细胞的出生和死亡,然后影响周围邻居的邻居数。并且为了不影响后续细胞的判断,需要新旧邻居数两个状态,用旧邻居数决定自己生死,而自己的生死变化影响周围邻居的新邻居数。另外如果某个格子的新旧邻居数不变则状态不变,增加一个changed字段来表示。
下面分别是旧、新两种算法。

 #include <stdio.h>
#include <stdlib.h> #define ROW 20
#define COL 60
#define FILEPATH "1.txt" int countNbor(char data[][COL],int i,int j);
void world(void); int main(void)
{
world();
return ;
} void world(void)
{
int i,j;
char data[ROW][COL];
char temp[ROW][COL];
int time=; FILE *fp=fopen(FILEPATH,"r"); for(i=;i<ROW;i++)
{
for(j=;j<COL;j++)
{
if(fgetc(fp)=='*') //表示细胞的字符
temp[i][j]=data[i][j]='*';
else temp[i][j]=data[i][j]=' ';
}
fgetc(fp);
}
fclose(fp); while()
{
time++; system("CLS");
for(i=;i<ROW;i++)
{
for(j=;j<COL;j++)
printf("%c",data[i][j]);
printf("\n");
}
printf("次数:%d\n",time); system("PAUSE>NUL"); for(i=;i<ROW;i++)
for(j=;j<COL;j++)
switch(countNbor(temp,i,j))
{
case :
data[i][j]='*';
break;
case :
break;
default:
data[i][j]=' ';
break;
} for(i=;i<ROW;i++)
for(j=;j<COL;j++)
temp[i][j]=data[i][j];
} } int countNbor(char data[][COL],int i,int j)
{
int m,n;
int count=; for(m=i-;m<=i+;m++)
for(n=j-;n<=j+;n++)
if( (m==i&&n==j) ||m<||n<||m==ROW||n==COL)
continue;
else if(data[m][n]=='*') count++; return count;
}

old.c

 #include <stdio.h>
#include <stdlib.h> #define ROW 20
#define COL 60
#define FILEPATH "1.txt" typedef struct{
int live; //1、0表生死
int nbor_old; //旧邻居数,用于判断细胞生死
int nbor_new; //新邻居数,用于下一时刻
int changed; //邻居数是否变化
}Cell; typedef struct{
Cell cell[ROW+][COL+]; //+2留边
int lives_num; //细胞数目
int time_count; //第几轮
}World; void showWorld(World *world);
void sendNbor(Cell cell[][COL+],int i,int j,int live);
void processCell(World *world,int i,int j);
void iniWorld(World *world);
void runWorld(void); int main(void)
{
runWorld();
return ;
} void runWorld(void)
{
World world;
Cell (*cell)[COL+]=world.cell;
int i,j; //从文件初始化
iniWorld(&world); while()
{ world.time_count++;
showWorld(&world); //前提 cell[i][j].nbor_old==cell[i][j].nbor_new
//邻居数不变则状态不变,不用处理
for(i=;i<=ROW;i++)
for(j=;j<=COL;j++)
if(cell[i][j].changed)
processCell(&world,i,j); //判断自身,影响周围 for(i=;i<=ROW;i++)
for(j=;j<=COL;j++)
if(cell[i][j].nbor_old==cell[i][j].nbor_new)
cell[i][j].changed=;
else
{
cell[i][j].changed=;
cell[i][j].nbor_old=cell[i][j].nbor_new;
} }
} void iniWorld(World *world)
{
int i,j;
FILE *fp=fopen(FILEPATH,"r");
Cell (*cell)[COL+]=world->cell; world->time_count=;
world->lives_num=; for(i=;i<=ROW;i++)
{
for(j=;j<=COL;j++)
{
if(fgetc(fp)=='*') //表示细胞的字符
{
cell[i][j].live=;
world->lives_num++;
}
else
cell[i][j].live=; cell[i][j].nbor_new=cell[i][j].nbor_old=;
cell[i][j].changed=; //为了第一次循环每个细胞都能处理
}
fgetc(fp); //换行符
} fclose(fp); //填充nbor_old和nbor_new
for(i=;i<=ROW;i++)
for(j=;j<=COL;j++)
if(cell[i][j].live)
{
cell[i-][j-].nbor_old =++cell[i-][j-].nbor_new;
cell[i-][j].nbor_old =++cell[i-][j].nbor_new;
cell[i-][j+].nbor_old =++cell[i-][j+].nbor_new;
cell[i][j-].nbor_old =++cell[i][j-].nbor_new;
cell[i][j+].nbor_old =++cell[i][j+].nbor_new;
cell[i+][j-].nbor_old =++cell[i+][j-].nbor_new;
cell[i+][j].nbor_old =++cell[i+][j].nbor_new;
cell[i+][j+].nbor_old =++cell[i+][j+].nbor_new;
}
} //由old决定生死,并改变周围细胞的new
void processCell(World *world,int i,int j)
{
Cell (*cell)[COL+]=world->cell; switch(cell[i][j].nbor_old)
{
case :
if(!cell[i][j].live)
{
cell[i][j].live=;
sendNbor(cell,i,j,);
world->lives_num++;
}
break;
case : //不变
break;
default:
if(cell[i][j].live)
{
cell[i][j].live=;
sendNbor(cell,i,j,-);
world->lives_num--;
}
break;
}
} //细胞状态改变后,影响周围细胞的邻居值,live为-1或1
void sendNbor(Cell cell[][COL+],int i,int j,int live)
{
cell[i-][j-].nbor_new+=live;
cell[i-][j].nbor_new+=live;
cell[i-][j+].nbor_new+=live;
cell[i][j-].nbor_new+=live;
cell[i][j+].nbor_new+=live;
cell[i+][j-].nbor_new+=live;
cell[i+][j].nbor_new+=live;
cell[i+][j+].nbor_new+=live;
} void showWorld(World *world)
{
int i,j; system("CLS"); for(i=;i<=ROW;i++)
{
for(j=;j<=COL;j++)
{
if(world->cell[i][j].live)
printf("*");
else printf(" ");
}
printf("\n");
}
printf("细胞数:%d\n次数:%d\n",world->lives_num,world->time_count); system("PAUSE>NUL");
}

new.c