Chinaunix首页 | 论坛 | 博客
  • 博客访问: 155109
  • 博文数量: 39
  • 博客积分: 2713
  • 博客等级: 少校
  • 技术积分: 420
  • 用 户 组: 普通用户
  • 注册时间: 2010-09-25 00:05
文章分类

全部博文(39)

文章存档

2012年(1)

2011年(2)

2010年(36)

分类: LINUX

2010-11-14 13:48:28

代码用到了NCURSES库。编译的时候链一下ncurses库就可以了,如:
cc -Wall -O2 -o mine mine.c -lncurses


首先放出界面欣赏一下,眼晕的看看外面再继续 ==!:

   

 

 代码:

 

代码
  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 #include <sys/types.h>
  5 #include <sys/wait.h>
  6 #include <sys/select.h>
  7 #include <time.h>
  8 #include <signal.h>
  9 #include <unistd.h>
 10 #include <ncurses.h>
 11 
 12 /* 雷区的范围 */
 13 #define MINEAREA_WIDTH      9
 14 #define MINEAREA_LENGTH     9
 15 /* 雷的个数 */
 16 #define MINE_NUMBER         10
 17 
 18 /*
 19  * 将每个方块的状态分类:
 20  * 1.初始状态
 21  * 2.判定为雷(也就是通常的插旗)
 22  * 3.排除(若周边有n个雷则显示为n,0则显示为空,用-1来表示雷)
 23  */
 24 #define SQUARE_INIT         0
 25 #define SQUARE_FLAG         1
 26 #define SQUARE_CLEAN        2
 27 #define SQUARE_ZERO         0
 28 #define SQUARE_MINE         -1
 29 
 30 /* 显示图形 */
 31 #define GRAPH_INIT          '.'
 32 #define GRAPH_MINE          '@'
 33 #define GRAPH_NULL          ' '
 34 #define GRAPH_FLAG          'F'
 35 
 36 #define NEWLINE             addch('\n')
 37 #define _W(y)               (y * 2 + 3)
 38 #define _L(x)               (x * 3 + 1)
 39 /* 设置光标 */
 40 #define SET_CURSOR(y, x)    mvchgat(_W(y), _L(x), 2, A_REVERSE, 0, NULL)
 41 #define CLEAN_CURSOR(y, x)  mvchgat(_W(y), _L(x), 2, A_NORMAL,  0, NULL)
 42 
 43 #define WPRINT_NUMBER(y, x, v)   \
 44     mvprintw(y, x, "%d", v)
 45 #define WPRINT_CHAR(y, x, c)     \
 46     mvaddch(y, x, c)
 47 
 48 /* 光标的位置 */
 49 int g_cur_y = 0;
 50 int g_cur_x = 0;
 51 
 52 struct square_t {
 53     int type;
 54     int mine;
 55 };
 56 
 57 /* timer process function */
 58 int timer_p();
 59 void sig_refresh_time(int signum);
 60 
 61 int init_mine(struct square_t square[MINEAREA_WIDTH][MINEAREA_LENGTH]);
 62 int check_yx(int y, int x);
 63 int game_loop(struct square_t square[MINEAREA_WIDTH][MINEAREA_LENGTH]);
 64 int clean_zero_squares(struct square_t square[MINEAREA_WIDTH][MINEAREA_LENGTH], int cur_y, int cur_x);
 65 
 66 /* window functions */
 67 int win_init(int width, int length, int mine_num);
 68 int win_refresh(struct square_t square[MINEAREA_WIDTH][MINEAREA_LENGTH], int width, int length, int mines);
 69 int win_refresh_remine_mines(int mines);
 70 int win_refresh_secs(int secs);
 71 int win_mv_cursor(int delta_y, int delta_x, int width, int length);
 72 int win_destroy();
 73 int win_bang();
 74 int win_win();
 75 int win_game_over();
 76 
 77 int main()
 78 {
 79     int pid_timer;
 80     int pid_main;
 81 
 82     switch (pid_timer = fork()) {
 83     case 0:
 84         /* timer进程,用作计时器 */
 85         timer_p();
 86         _exit(0);
 87     case -1:
 88         perror("fork() error!");
 89         return -1;
 90     default:
 91         /* main process */
 92         break;
 93     }
 94 
 95     pid_main = getpid();
 96 
 97     /* SIGUSR1信号用来刷新显示时间 */
 98     if (signal(SIGUSR1, sig_refresh_time) == SIG_ERR)
 99         return -1;
100 
101     struct square_t square[MINEAREA_WIDTH][MINEAREA_LENGTH];
102 
103     if (init_mine(square) == -1return -1;
104 
105     win_init(MINEAREA_WIDTH, MINEAREA_LENGTH, MINE_NUMBER);
106 
107     /* 主循环 */
108     game_loop(square);
109 
110     win_game_over();
111 
112     /* 主进程结束前需要结束timer子进程 */
113     kill(pid_timer, SIGKILL);
114 
115     int key = -1;
116     do {
117         key = getch();
118     }
119     while (key != 'y' && key != 'Y');
120 
121     wait(NULL);
122     win_destroy();
123 
124     return 0;
125 }
126 
127 /* 初始化雷区信息 */
128 int init_mine(struct square_t square[MINEAREA_WIDTH][MINEAREA_LENGTH])
129 {
130     if (square == NULL)
131         return -1;
132 
133     printf("waiting...\n");
134 
135     int n,m;
136     for (n = 0; n < 9++n) {
137         for (m = 0; m < 9++m) {
138             square[n][m].type = 0;
139             square[n][m].mine = 0;
140         }
141     }
142 
143     int i;
144     int y, x;
145 
146     srandom((int)time(NULL));
147 
148     for (i = 0; i < MINE_NUMBER; ++i) {
149         y = random() % MINEAREA_WIDTH;
150         x = random() % MINEAREA_LENGTH;
151 
152         if (square[y][x].mine == SQUARE_MINE) {
153             --i;
154         }
155         else {
156             square[y][x].mine = SQUARE_MINE;
157 
158             if (check_yx(y-1, x  ) == 0 && square[y-1][x  ].mine != SQUARE_MINE)
159                 ++square[y-1][x  ].mine;
160 
161             if (check_yx(y+1, x  ) == 0 && square[y+1][x  ].mine != SQUARE_MINE)
162                 ++square[y+1][x  ].mine;
163 
164             if (check_yx(y  , x-1== 0 && square[y  ][x-1].mine != SQUARE_MINE)
165                 ++square[y  ][x-1].mine;
166 
167             if (check_yx(y  , x+1== 0 && square[y  ][x+1].mine != SQUARE_MINE)
168                 ++square[y  ][x+1].mine;
169 
170             if (check_yx(y-1, x-1== 0 && square[y-1][x-1].mine != SQUARE_MINE)
171                 ++square[y-1][x-1].mine;
172 
173             if (check_yx(y+1, x-1== 0 && square[y+1][x-1].mine != SQUARE_MINE)
174                 ++square[y+1][x-1].mine;
175 
176             if (check_yx(y-1, x+1== 0 && square[y-1][x+1].mine != SQUARE_MINE)
177                 ++square[y-1][x+1].mine;
178 
179             if (check_yx(y+1, x+1== 0 && square[y+1][x+1].mine != SQUARE_MINE)
180                 ++square[y+1][x+1].mine;
181         }
182     }
183 
184     return 0;
185 }
186 
187 int check_yx(int y, int x)
188 {
189     if (y >= 0
190         && y < MINEAREA_WIDTH
191         && x >= 0
192         && x < MINEAREA_LENGTH)
193     {
194         return 0;
195     }
196 
197     return -1;
198 }
199 
200 /* 主循环 */
201 int game_loop(struct square_t square[MINEAREA_WIDTH][MINEAREA_LENGTH])
202 {
203     fd_set rfd;
204     FD_ZERO(&rfd);
205     FD_SET(0&rfd);
206 
207     static int sweeped_mines = 0/* 判定正确的雷数 */
208 
209     int ret;
210     int input;
211     int remain_mines = MINE_NUMBER;
212 
213     while (1) {
214         if ((ret = select(1&rfd, NULL, NULL, NULL)) <= 0) {
215             //return -1;    //当程序被信号中断时select可能会返回-1
216             continue;
217         }
218 
219         switch (input = getch()) {
220         /* w,s,a,d方向键 */
221         case 'w':
222         case 'W':
223             win_mv_cursor(-10, MINEAREA_WIDTH, MINEAREA_LENGTH);
224             break;
225         case 's':
226         case 'S':
227             win_mv_cursor(+10, MINEAREA_WIDTH, MINEAREA_LENGTH);
228             break;
229         case 'a':
230         case 'A':
231             win_mv_cursor(0-1, MINEAREA_WIDTH, MINEAREA_LENGTH);
232             break;
233         case 'd':
234         case 'D':
235             win_mv_cursor(0+1, MINEAREA_WIDTH, MINEAREA_LENGTH);
236             break;
237 
238         /* 插旗 */
239         case 'j':
240         case 'J':
241             if (square[g_cur_y][g_cur_x].type == SQUARE_INIT) {
242                 square[g_cur_y][g_cur_x].type = SQUARE_FLAG;
243                 --remain_mines;
244 
245                 if (square[g_cur_y][g_cur_x].mine == SQUARE_MINE)
246                     ++sweeped_mines;
247             }
248             else if (square[g_cur_y][g_cur_x].type == SQUARE_FLAG) {
249                 square[g_cur_y][g_cur_x].type = SQUARE_INIT;
250                 ++remain_mines;
251 
252                 if (square[g_cur_y][g_cur_x].mine == SQUARE_MINE)
253                     --sweeped_mines;
254             }
255             else
256                 break;
257 
258             if (sweeped_mines == MINE_NUMBER) {
259                 win_win();
260                 goto GAME_OVER;
261             }
262 
263             win_refresh(square, MINEAREA_WIDTH, MINEAREA_LENGTH, remain_mines);
264             break;
265 
266         /* 打开方块 */
267         case 'k':
268         case 'K':
269             if (square[g_cur_y][g_cur_x].type == SQUARE_CLEAN)
270                 break;
271             else if (square[g_cur_y][g_cur_x].mine == SQUARE_MINE) {
272                 win_bang();
273 
274                 int n, m;
275                 for (n = 0; n < MINEAREA_WIDTH; ++n) {
276                     for (m = 0; m < MINEAREA_LENGTH; ++m) {
277                         square[n][m].type = SQUARE_CLEAN;
278                     }
279                 }
280 
281                 win_refresh(square, MINEAREA_WIDTH, MINEAREA_LENGTH, remain_mines);
282                 goto GAME_OVER;
283             }
284 
285             square[g_cur_y][g_cur_x].type = SQUARE_CLEAN;
286 
287             if (square[g_cur_y][g_cur_x].mine == SQUARE_ZERO)
288                 clean_zero_squares(square, g_cur_y, g_cur_x);
289 
290             win_refresh(square, MINEAREA_WIDTH, MINEAREA_LENGTH, remain_mines);
291             break;
292 
293         /* 退出 */
294         case 'q':
295         case 'Q':
296             goto GAME_OVER;
297 
298         default:
299             break;
300         }
301     }
302 
303 GAME_OVER:
304     return 0;
305 }
306 
307 /* 如果打开的方块下面是0,则自动打开所有周围为0的方块 */
308 int clean_zero_squares(struct square_t square[MINEAREA_WIDTH][MINEAREA_LENGTH], int cur_y, int cur_x)
309 {
310     if (check_yx(cur_y - 1, cur_x) == 0
311         && square[cur_y - 1][cur_x].mine == SQUARE_ZERO
312         && square[cur_y - 1][cur_x].type != SQUARE_CLEAN)
313     {
314         square[cur_y - 1][cur_x].type = SQUARE_CLEAN;
315         clean_zero_squares(square, cur_y - 1, cur_x);
316     }
317 
318     if (check_yx(cur_y + 1, cur_x) == 0
319         && square[cur_y + 1][cur_x].mine == SQUARE_ZERO
320         && square[cur_y + 1][cur_x].type != SQUARE_CLEAN)
321     {
322         square[cur_y + 1][cur_x].type = SQUARE_CLEAN;
323         clean_zero_squares(square, cur_y + 1, cur_x);
324     }
325 
326     if (check_yx(cur_y, cur_x - 1== 0
327         && square[cur_y][cur_x - 1].mine == SQUARE_ZERO
328         && square[cur_y][cur_x - 1].type != SQUARE_CLEAN)
329     {
330         square[cur_y][cur_x - 1].type = SQUARE_CLEAN;
331         clean_zero_squares(square, cur_y, cur_x - 1);
332     }
333 
334     if (check_yx(cur_y, cur_x + 1== 0
335         && square[cur_y][cur_x + 1].mine == SQUARE_ZERO
336         && square[cur_y][cur_x + 1].type != SQUARE_CLEAN)
337     {
338         square[cur_y][cur_x + 1].type = SQUARE_CLEAN;
339         clean_zero_squares(square, cur_y, cur_x + 1);
340     }
341 
342     return 0;
343 }
344 
345 /*****************************************************************************/
346 /* 初始化显示界面 */
347 int win_init(int width, int length, int mine_num)
348 {
349     initscr();
350     raw();
351     noecho();
352     keypad(stdscr, TRUE);
353     curs_set(0);
354     refresh();
355 
356     win_refresh_remine_mines(MINE_NUMBER);
357     win_refresh_secs(0);
358 
359     int frame_width  = width  * 2 + 1;
360     int frame_length = length * 3 + 1;
361     char *line = NULL;
362     line = (char*)malloc((frame_length + 1* sizeof(char));
363     memset(line, '-', frame_length);
364     *(line + frame_length) = '\0';
365     mvprintw(20, line);NEWLINE;
366 
367     int i, j;
368     for (j = 0; j < frame_width - 2++j) {
369         addch('|');
370         for (i = 0; i < length * 2 + 1 - 2++i) {
371             if (j % 2 == 0) {
372                 if (i % 2 == 0) {
373                     addch(GRAPH_INIT);addch(' ');
374                 }
375                 else {
376                     addch('|');
377                 }
378             }
379             else {
380                 if (i % 2 == 0) {
381                     addch('-');addch('-');
382                 }
383                 else {
384                     addch('+');
385                 }
386             }
387         }
388         addch('|');NEWLINE;
389     }
390 
391     printw(line);NEWLINE;
392 
393     /* set cursor position */
394     SET_CURSOR(g_cur_y, g_cur_x);
395 
396     refresh();
397     return 0;
398 }
399 
400 /* 刷新显示界面 */
401 int win_refresh(struct square_t square[MINEAREA_WIDTH][MINEAREA_LENGTH], int width, int length, int mines)
402 {
403     if (square == NULL)
404         return -1;
405 
406     win_refresh_remine_mines(mines);
407 
408     int j, i;
409     for (j = 0; j < width; ++j) {
410         for (i = 0; i < length; ++i) {
411             switch (square[j][i].type) {
412             case SQUARE_INIT:
413                 WPRINT_CHAR(_W(j), _L(i), GRAPH_INIT);
414                 break;
415             case SQUARE_FLAG:
416                 WPRINT_CHAR(_W(j), _L(i), GRAPH_FLAG);
417                 break;
418             case SQUARE_CLEAN:
419                 switch (square[j][i].mine) {
420                 case SQUARE_MINE:
421                     WPRINT_CHAR(_W(j), _L(i), GRAPH_MINE);
422                     break;
423                 case SQUARE_ZERO:
424                     WPRINT_CHAR(_W(j), _L(i), GRAPH_NULL);
425                     break;
426                 default:
427                     WPRINT_NUMBER(_W(j), _L(i), square[j][i].mine);
428                     break;
429                 }
430                 break;
431             default:
432                 break;
433             }
434         }
435     }
436 
437     refresh();
438 
439     return 0;
440 }
441 
442 int win_refresh_remine_mines(int mines)
443 {
444     mvprintw(00"Mines: %d", mines);
445     mvprintw(10"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
446     refresh();
447     return 0;
448 }
449 
450 int win_refresh_secs(int secs)
451 {
452     mvprintw(015"Seconds: %d", secs);
453     refresh();
454     return 0;
455 }
456 
457 
458 int win_mv_cursor(int delta_y, int delta_x, int width, int length)
459 {
460     CLEAN_CURSOR(g_cur_y, g_cur_x);
461 
462     if (g_cur_y + delta_y < width && g_cur_y + delta_y >= 0)
463         g_cur_y += delta_y;
464 
465     if (g_cur_x + delta_x < length && g_cur_x + delta_x >= 0)
466         g_cur_x += delta_x;
467 
468     SET_CURSOR(g_cur_y, g_cur_x);
469 
470     refresh();
471 
472     return 0;
473 }
474 
475 int win_destroy()
476 {
477     endwin();
478 
479     return 0;
480 }
481 
482 int win_bang()
483 {
484     mvprintw(00"BANG!!!!");
485     refresh();
486     return 0;
487 }
488 
489 int win_win()
490 {
491     mvprintw(00"WIN!!!!");
492     refresh();
493     return 0;
494 }
495 
496 int win_game_over()
497 {
498     mvprintw(10"Game Over!");
499     mvprintw(10"Press 'y' or 'Y' to end.");
500     refresh();
501     return 0;
502 }
503 
504 /*****************************************************************************/
505 int timer_p()
506 {
507     /* 每秒钟给主进程发一次信号 */
508     do {
509         sleep(1);
510         kill(getppid(), SIGUSR1);
511     }
512     while (1);
513 
514     return 0;
515 }
516 
517 void sig_refresh_time(int signum)
518 {
519     static int secs = 0;
520     win_refresh_secs(++secs);
521 }
522 

 

 

 

这里给出我自己编的一个可执行文件(ubuntu 10.4):

 /Files/dave_cn/mine.zip

 

-- END --

阅读(2016) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2010-11-15 15:59:56

很好的, 收藏了 推荐一个博客,提供很多免费软件编程电子书下载: http://free-ebooks.appspot.com