迷上了这种根据简单规则不断演化的东西,自己实现了下。 算法:
用两个二维数组,一个用来存储每个格子的状态,另一个用来记录临时状态,计算后写入第一个数组。边界以外的全部认为是死亡的格子。规则是普通的B3/S23。加入了信号量处理,可以方便被"kill -USR1 pid"却正常结束。没有图形界面全是打印,形状大小可根据命令行参数调节。
C实现(代码颜色为autumn):
001 #include
002 #include
003 #include
004 #include
005 #include
006 #include
007
008 #define LINE 30
009
010 char *g_version = "0.1";
011 int g_length = 0;
012 char g_symbol = '*';
013 useconds_t g_interval = 100000;
014
015
016 void usage()
017 {
018 printf("\nUsage:\t./game_of_life [-V] [-h] ...\n");
019 printf("\t-l, --length\t\tspecify the side length\n");
020 printf("\t-s, --symbol\t\tspecify the print symbol\n");
021 printf("\t-i, --interval\t\tspecify the evolution interval(microsecond)\n");
022 printf("\t-V, --version\t\tPrint the software version\n");
023 printf("\t-h, --help\t\tPrint the usage\n");
024 printf("\n\nExample: ./game_of_life -l 50 -s '#'\n\n");
025
026 return;
027 }
028
029 void parseArg(int argc, char **argv)
030 {
031 int opt;
032 opterr = 0;
033
034 struct option long_opts[] = {
035 {"length", 1, NULL, 'l'},
036 {"symbol", 1, NULL, 's'},
037 {"interval", 1, NULL, 'i'},
038 {"version", 0, NULL, 'V'},
039 {"help", 0, NULL, 'h'},
040 {NULL, 0, NULL, 0}
041 };
042
043 while ( (opt = getopt_long(argc, argv, "l:s:i:Vh", long_opts, NULL)) != -1 )
044 {
045 switch(opt)
046 {
047 case 'l':
048 g_length = atoi(optarg);
049 break;
050 case 's':
051 g_symbol = *optarg;
052 break;
053 case 'i':
054 g_interval = atoi(optarg);
055 break;
056 case 'V':
057 printf("game_of_life version: %s\n", g_version);
058 exit(0);
059 case '?':
060 printf("Unknown parameter!\n\n");
061 case 'h':
062 usage();
063 exit(0);
064 }
065 }
066
067 return;
068 }
069
070 char randNum()
071 {
072 /* generate a number in (0,2) */
073 int random = (int)(2.0 * ( rand() / (RAND_MAX + 1.0) ));
074 if (random == 1)
075 return g_symbol;
076 else
077 return '\0';
078 }
079
080 int init(char ***ppp_area)
081 {
082 int i, j;
083
084 /* set the pseudo-random seed */
085 struct timeval tseed;
086 if (gettimeofday(&tseed, NULL) == -1)
087 return -1;
088 srand(tseed.tv_sec ^ tseed.tv_usec);
089
090 /* set the windows area */
091 if (g_length == 0)
092 g_length = 100;
093 else if (g_length > 200)
094 g_length = 130;
095 else if (g_length < 10)
096 g_length = 10;
097
098 *ppp_area = (char **)malloc(sizeof(char *) * LINE);
099 if (*ppp_area == NULL)
100 return -1;
101
102 for (i = 0; i < LINE; ++i)
103 {
104 (*ppp_area)[i] = (char *)malloc(sizeof(char) * g_length);
105 for (j = 0; j < g_length; ++j)
106 (*ppp_area)[i][j] = randNum();
107 }
108
109 return 0;
110 }
111
112 void showStat(char **pp_area)
113 {
114 int i, j;
115
116 for (i = 0; i < LINE; ++i)
117 {
118 for (j = 0; j < g_length; ++j)
119 {
120 if (pp_area[i][j] == '\0')
121 putchar(' ');
122 else
123 putchar(pp_area[i][j]);
124 }
125 putchar('\n');
126 }
127 putchar('\n');
128
129 usleep(g_interval);
130
131 return;
132 }
133
134 void evolvement(char ***ppp_area)
135 {
136 int i, j;
137 char tmp_area[LINE][g_length];
138 char **pp_area = *ppp_area;
139
140 for (i = 0; i < LINE; ++i)
141 for (j = 0; j < g_length; ++j)
142 tmp_area[i][j] = pp_area[i][j];
143
144 /* i = 0 */
145 i = 0;
146 for (j = 0; j < g_length; ++j)
147 {
148 int lives = 0;
149
150 if (j == 0)
151 {
152 if (tmp_area[i][j+1] != '\0') ++lives;
153 if (tmp_area[i+1][j] != '\0') ++lives;
154 if (tmp_area[i+1][j+1] != '\0') ++lives;
155 }
156 else if (j + 1 == g_length)
157 {
158 if (tmp_area[i][j-1] != '\0') ++lives;
159 if (tmp_area[i+1][j-1] != '\0') ++lives;
160 if (tmp_area[i+1][j] != '\0') ++lives;
161 }
162 else
163 {
164 if (tmp_area[i][j-1] != '\0') ++lives;
165 if (tmp_area[i][j+1] != '\0') ++lives;
166 if (tmp_area[i+1][j-1] != '\0') ++lives;
167 if (tmp_area[i+1][j] != '\0') ++lives;
168 if (tmp_area[i+1][j+1] != '\0') ++lives;
169 }
170
171 /* 3 reproduce, 2 no change */
172 if (lives == 3)
173 pp_area[i][j] = g_symbol;
174 else if (lives == 2)
175 ;
176 else
177 pp_area[i][j] = '\0';
178 }
179
180 /* 0 < i < LINE - 1 */
181 for (i = 1; i < LINE - 1; ++i)
182 {
183 for (j = 0; j < g_length; ++j)
184 {
185 int lives = 0;
186
187 if (j == 0)
188 {
189 if (tmp_area[i-1][j] != '\0') ++lives;
190 if (tmp_area[i-1][j+1] != '\0') ++lives;
191 if (tmp_area[i][j+1] != '\0') ++lives;
192 if (tmp_area[i+1][j] != '\0') ++lives;
193 if (tmp_area[i+1][j+1] != '\0') ++lives;
194 }
195 else if (j + 1 == LINE)
196 {
197 if (tmp_area[i-1][j-1] != '\0') ++lives;
198 if (tmp_area[i-1][j] != '\0') ++lives;
199 if (tmp_area[i][j-1] != '\0') ++lives;
200 if (tmp_area[i+1][j-1] != '\0') ++lives;
201 if (tmp_area[i+1][j] != '\0') ++lives;
202 }
203 else
204 {
205 if (tmp_area[i-1][j-1] != '\0') ++lives;
206 if (tmp_area[i-1][j] != '\0') ++lives;
207 if (tmp_area[i-1][j+1] != '\0') ++lives;
208 if (tmp_area[i][j-1] != '\0') ++lives;
209 if (tmp_area[i][j+1] != '\0') ++lives;
210 if (tmp_area[i+1][j-1] != '\0') ++lives;
211 if (tmp_area[i+1][j] != '\0') ++lives;
212 if (tmp_area[i+1][j+1] != '\0') ++lives;
213 }
214
215 if (lives == 3)
216 pp_area[i][j] = g_symbol;
217 else if (lives == 2)
218 ;
219 else
220 pp_area[i][j] = '\0';
221 }
222 }
223
224 /* i = LINE - 1 */
225 i = LINE - 1;
226 for (j = 0; j < g_length; ++j)
227 {
228 int lives = 0;
229
230 if (j == 0)
231 {
232 if (tmp_area[i-1][j] != '\0') ++lives;
233 if (tmp_area[i-1][j+1] != '\0') ++lives;
234 if (tmp_area[i][j+1] != '\0') ++lives;
235 }
236 else if (j + 1 == g_length)
237 {
238 if (tmp_area[i-1][j-1] != '\0') ++lives;
239 if (tmp_area[i-1][j] != '\0') ++lives;
240 if (tmp_area[i][j-1] != '\0') ++lives;
241 }
242 else
243 {
244 if (tmp_area[i-1][j-1] != '\0') ++lives;
245 if (tmp_area[i-1][j] != '\0') ++lives;
246 if (tmp_area[i-1][j+1] != '\0') ++lives;
247 if (tmp_area[i][j-1] != '\0') ++lives;
248 if (tmp_area[i][j+1] != '\0') ++lives;
249 }
250
251 if (lives == 3)
252 pp_area[i][j] = g_symbol;
253 else if (lives == 2)
254 ;
255 else
256 pp_area[i][j] = '\0';
257 }
258
259 return;
260 }
261
262 void fn(int sig)
263 {
264 exit(1);
265 }
266 int main(int argc, char **argv)
267 {
268 char **area;
269
270 parseArg(argc, argv);
271
272 signal(SIGUSR1, fn);
273
274 /* malloc area, don't forget to free! */
275 if (init(&area) == -1)
276 {
277 printf("Initialization failed!\n");
278 return 1;
279 }
280
281 for (;;)
282 {
283 showStat(area);
284 evolvement(&area);puts("\033[2J");
285 }
286
287 int n;
288 for (n = 0; n < LINE; ++n)
289 free(area[n]);
290 free(area);
291
292 return 0;
293 }
阅读(1461) | 评论(0) | 转发(0) |