The game of life(生命游戏)新算法
我写了一种常见的实现算法,和另一种新算法,即不是每次循环计算每个细胞的周围细胞数来产生下一时刻,而是每次每个产生状态变化的细胞主动通知周围的邻居,因此每个细胞增加一个用来记录邻居数的字段。由邻居数决定每个细胞的出生和死亡,然后影响周围邻居的邻居数。并且为了不影响后续细胞的判断,需要新旧邻居数两个状态,用旧邻居数决定自己生死,而自己的生死变化影响周围邻居的新邻居数。另外如果某个格子的新旧邻居数不变则状态不变,增加一个changed字段来表示。
下面分别是旧、新两种算法。
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 #define ROW 20 5 #define COL 60 6 #define FILEPATH "1.txt" 7 8 9 int countNbor(char data[][COL],int i,int j); 10 void world(void); 11 12 13 int main(void) 14 { 15 world(); 16 return 0; 17 } 18 19 void world(void) 20 { 21 int i,j; 22 char data[ROW][COL]; 23 char temp[ROW][COL]; 24 int time=0; 25 26 27 FILE *fp=fopen(FILEPATH,"r"); 28 29 for(i=0;i<ROW;i++) 30 { 31 for(j=0;j<COL;j++) 32 { 33 if(fgetc(fp)=='*') //表示细胞的字符 34 temp[i][j]=data[i][j]='*'; 35 else temp[i][j]=data[i][j]=' '; 36 } 37 fgetc(fp); 38 } 39 fclose(fp); 40 41 while(1) 42 { 43 time++; 44 45 system("CLS"); 46 for(i=0;i<ROW;i++) 47 { 48 for(j=0;j<COL;j++) 49 printf("%c",data[i][j]); 50 printf("\n"); 51 } 52 printf("次数:%d\n",time); 53 54 system("PAUSE>NUL"); 55 56 for(i=0;i<ROW;i++) 57 for(j=0;j<COL;j++) 58 switch(countNbor(temp,i,j)) 59 { 60 case 3: 61 data[i][j]='*'; 62 break; 63 case 2: 64 break; 65 default: 66 data[i][j]=' '; 67 break; 68 } 69 70 for(i=0;i<ROW;i++) 71 for(j=0;j<COL;j++) 72 temp[i][j]=data[i][j]; 73 } 74 75 } 76 77 int countNbor(char data[][COL],int i,int j) 78 { 79 int m,n; 80 int count=0; 81 82 for(m=i-1;m<=i+1;m++) 83 for(n=j-1;n<=j+1;n++) 84 if( (m==i&&n==j) ||m<0||n<0||m==ROW||n==COL) 85 continue; 86 else if(data[m][n]=='*') count++; 87 88 return count; 89 }
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 5 #define ROW 20 6 #define COL 60 7 #define FILEPATH "1.txt" 8 9 10 typedef struct{ 11 int live; //1、0表生死 12 int nbor_old; //旧邻居数,用于判断细胞生死 13 int nbor_new; //新邻居数,用于下一时刻 14 int changed; //邻居数是否变化 15 }Cell; 16 17 typedef struct{ 18 Cell cell[ROW+2][COL+2]; //+2留边 19 int lives_num; //细胞数目 20 int time_count; //第几轮 21 }World; 22 23 void showWorld(World *world); 24 void sendNbor(Cell cell[][COL+2],int i,int j,int live); 25 void processCell(World *world,int i,int j); 26 void iniWorld(World *world); 27 void runWorld(void); 28 29 30 int main(void) 31 { 32 runWorld(); 33 return 0; 34 } 35 36 37 void runWorld(void) 38 { 39 World world; 40 Cell (*cell)[COL+2]=world.cell; 41 int i,j; 42 43 //从文件初始化 44 iniWorld(&world); 45 46 while(1) 47 { 48 49 world.time_count++; 50 showWorld(&world); 51 52 //前提 cell[i][j].nbor_old==cell[i][j].nbor_new 53 //邻居数不变则状态不变,不用处理 54 for(i=1;i<=ROW;i++) 55 for(j=1;j<=COL;j++) 56 if(cell[i][j].changed) 57 processCell(&world,i,j); //判断自身,影响周围 58 59 for(i=1;i<=ROW;i++) 60 for(j=1;j<=COL;j++) 61 if(cell[i][j].nbor_old==cell[i][j].nbor_new) 62 cell[i][j].changed=0; 63 else 64 { 65 cell[i][j].changed=1; 66 cell[i][j].nbor_old=cell[i][j].nbor_new; 67 } 68 69 } 70 } 71 72 73 74 void iniWorld(World *world) 75 { 76 int i,j; 77 FILE *fp=fopen(FILEPATH,"r"); 78 Cell (*cell)[COL+2]=world->cell; 79 80 81 world->time_count=0; 82 world->lives_num=0; 83 84 for(i=1;i<=ROW;i++) 85 { 86 for(j=1;j<=COL;j++) 87 { 88 if(fgetc(fp)=='*') //表示细胞的字符 89 { 90 cell[i][j].live=1; 91 world->lives_num++; 92 } 93 else 94 cell[i][j].live=0; 95 96 cell[i][j].nbor_new=cell[i][j].nbor_old=0; 97 cell[i][j].changed=1; //为了第一次循环每个细胞都能处理 98 } 99 fgetc(fp); //换行符 100 } 101 102 fclose(fp); 103 104 //填充nbor_old和nbor_new 105 for(i=1;i<=ROW;i++) 106 for(j=1;j<=COL;j++) 107 if(cell[i][j].live) 108 { 109 cell[i-1][j-1].nbor_old =++cell[i-1][j-1].nbor_new; 110 cell[i-1][j].nbor_old =++cell[i-1][j].nbor_new; 111 cell[i-1][j+1].nbor_old =++cell[i-1][j+1].nbor_new; 112 cell[i][j-1].nbor_old =++cell[i][j-1].nbor_new; 113 cell[i][j+1].nbor_old =++cell[i][j+1].nbor_new; 114 cell[i+1][j-1].nbor_old =++cell[i+1][j-1].nbor_new; 115 cell[i+1][j].nbor_old =++cell[i+1][j].nbor_new; 116 cell[i+1][j+1].nbor_old =++cell[i+1][j+1].nbor_new; 117 } 118 } 119 120 121 //由old决定生死,并改变周围细胞的new 122 void processCell(World *world,int i,int j) 123 { 124 Cell (*cell)[COL+2]=world->cell; 125 126 switch(cell[i][j].nbor_old) 127 { 128 case 3: 129 if(!cell[i][j].live) 130 { 131 cell[i][j].live=1; 132 sendNbor(cell,i,j,1); 133 world->lives_num++; 134 } 135 break; 136 case 2: //不变 137 break; 138 default: 139 if(cell[i][j].live) 140 { 141 cell[i][j].live=0; 142 sendNbor(cell,i,j,-1); 143 world->lives_num--; 144 } 145 break; 146 } 147 } 148 149 150 151 152 //细胞状态改变后,影响周围细胞的邻居值,live为-1或1 153 void sendNbor(Cell cell[][COL+2],int i,int j,int live) 154 { 155 cell[i-1][j-1].nbor_new+=live; 156 cell[i-1][j].nbor_new+=live; 157 cell[i-1][j+1].nbor_new+=live; 158 cell[i][j-1].nbor_new+=live; 159 cell[i][j+1].nbor_new+=live; 160 cell[i+1][j-1].nbor_new+=live; 161 cell[i+1][j].nbor_new+=live; 162 cell[i+1][j+1].nbor_new+=live; 163 } 164 165 166 void showWorld(World *world) 167 { 168 int i,j; 169 170 system("CLS"); 171 172 for(i=1;i<=ROW;i++) 173 { 174 for(j=1;j<=COL;j++) 175 { 176 if(world->cell[i][j].live) 177 printf("*"); 178 else printf(" "); 179 } 180 printf("\n"); 181 } 182 printf("细胞数:%d\n次数:%d\n",world->lives_num,world->time_count); 183 184 system("PAUSE>NUL"); 185 }