自制生命游戏

生命游戏的介绍在这里: 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 }
posted @ 2012-11-16 20:40  leaforestd  阅读(206)  评论(0编辑  收藏  举报