自制生命游戏
生命游戏的介绍在这里: http://zh.wikipedia.org/wiki/%E7%94%9F%E5%91%BD%E6%B8%B8%E6%88%8F
最早在<Hackers>上面看到这个, 有点印象. 看wikipedia上的介绍也很简单, 三条规则:
对于平面上的任意点:
1. 四周(周围8个点)有2个生命时, 该点状态(有/无生命)不变.
2. 四周有3个生命时, 该点有生命.
3. 其他情况, 该点无生命.
用c实现了. 用一个row * column的全局数组作为table(考虑到生命的无中生有, 暂时想不出来其他结构), 用系统timer更新, ncurses.h绘图.
1 /* life.c: 2 * written by leaforestd@gmail.com 3 * compile: gcc -lcurses -o life life.c 4 */ 5 #include <curses.h> 6 #include <errno.h> 7 #include <stdlib.h> 8 #include <signal.h> 9 #include <sys/time.h> 10 #include <unistd.h> /* for sleep() */ 11 12 #define LIFE 1 13 #define DEAD 0 14 #define ROW 40 15 #define COL 60 16 #define REFRESH_MSEC 200 /* 0.2s */ 17 18 char table[ROW][COL]; /* non-zero for life */ 19 20 void initgame(); 21 void inittable(); 22 void set_timer(); 23 void next_step(); 24 void display(); 25 void next_table(); 26 int life_around(int r, int c); 27 void unix_error(char *msg); 28 29 int main() 30 { 31 initgame(); 32 for (;;); 33 return 0; 34 } 35 36 void initgame() 37 { 38 initscr(); 39 noecho(); 40 curs_set(0); 41 inittable(); 42 display(); 43 set_timer(); 44 if (signal(SIGALRM, next_step) == SIG_ERR) { 45 unix_error("signal error"); 46 exit(-1); 47 } 48 } 49 50 void set_timer() 51 { 52 long refresh_usec = REFRESH_MSEC * 1000; 53 struct itimerval timer; 54 55 timer.it_interval.tv_sec = 0; 56 timer.it_interval.tv_usec = refresh_usec; 57 timer.it_value.tv_sec = 0; 58 timer.it_value.tv_usec = refresh_usec; 59 60 if (setitimer(ITIMER_REAL, &timer, 0) != 0) { 61 unix_error("setitimer error"); 62 exit(-1); 63 } 64 } 65 66 void inittable() /* set beginning cells */ 67 { 68 int r, c; 69 for (r = 20; r < 40; r++) { 70 for (c = 15; c < 25; c++) { 71 table[r][c] = 1; 72 } 73 } 74 } 75 76 void next_step() 77 { 78 next_table(); 79 display(); 80 } 81 82 void display() 83 { 84 int col, row; 85 86 erase(); 87 for (row = 0; row < ROW; row++) { 88 for (col = 0; col < COL; col++) { 89 if (table[row][col] != 0) { 90 move(row, col); 91 printw("@"); 92 } 93 } 94 } 95 refresh(); 96 } 97 98 void next_table() 99 { 100 int row, col, life; 101 102 for (row = 0; row < ROW; row++) { 103 for (col = 0; col < COL; col++) { 104 if ((life = life_around(row, col)) == 3) { 105 table[row][col] = 1; 106 } else if (life != 2) { 107 table[row][col] = 0; 108 } 109 } 110 } 111 } 112 113 int life_around(int r, int c) 114 { 115 int count = 0; 116 117 if ((r - 1 >= 0) && (c - 1 >= 0)) 118 count += table[r - 1][c - 1]; 119 if (r - 1 >= 0) 120 count += table[r - 1][c]; 121 if ((r - 1 >= 0) && (c + 1 < COL)) 122 count += table[r - 1][c + 1]; 123 if (c - 1 >= 0) 124 count += table[r][c - 1]; 125 if (c + 1 < COL) 126 count += table[r][c + 1]; 127 if ((r + 1 < ROW) && (c - 1 >= 0)) 128 count += table[r + 1][c - 1]; 129 if (r + 1 < ROW) 130 count += table[r + 1][c]; 131 if ((r + 1 < ROW) && (c + 1 < COL)) 132 count += table[r + 1][c + 1]; 133 134 return count; 135 } 136 137 void unix_error(char *msg) 138 { 139 fprintf(stderr, "%s: %s\n", msg, strerror(errno)); 140 }