LINUX 控制台运行的贪吃蛇程序 测试定时函数使用

编译 命令    gcc ./eat_snake.c   -I/usr/include -L/usr/lib -lncurses

 

方向键 或者 wasd 或者 小键盘 4568 控制

开局选择速度 值越小 越快(建议10)

p键暂停

x键退出

实现思路很简单 重新绘制输出缓冲

  1 #include <stdio.h>     //这个程序是写在用户空间运行的,非内核程序
  2 #include <sys/types.h> //中文名称为基本系统数据类型,此头文件还包含适当时应使用的多个基本派生类型。
  3 #include <sys/stat.h>  //这个头文件和文件调用相关
  4 #include <linux/input.h> 
  5 #include <unistd.h>
  6 #include <fcntl.h> //ioctl 与底层驱动交接
  7 #include <time.h>
  8 #include <curses.h>
  9 #include <stdlib.h>
 10 #include <signal.h>
 11 
 12 #define  MAP_X_LEN 30
 13 #define  MAP_Y_LEN 102
 14 
 15 int set_timer(int n_us);
 16 void timer_do();
 17 
 18 char snake_map[MAP_X_LEN][MAP_Y_LEN];
 19 int control=1;//决定执行怎么样的控制
 20 int sum_sec=0;
 21 int sum_get=0;
 22 char new_direct='V';
 23 int le=5,ifselectle=1;
 24 int restart=1;
 25 struct snake_body
 26 {
 27     struct snake_body *next;
 28     struct snake_body *pre;
 29     int x;
 30     int y;
 31     int if_fist;
 32 };
 33 struct snake_head
 34 {
 35     struct snake_body *first_body;
 36     struct snake_body *last_body;
 37     int x;
 38     int y;
 39     char direct;
 40     char keepdir;
 41     int len;
 42 };
 43 
 44 struct snake_head head;
 45 
 46 
 47 void make_apple()
 48 {
 49     int x,y;
 50     int xmax=MAP_X_LEN-2;
 51     int ymax=MAP_Y_LEN-2;
 52     srand((unsigned)time(NULL));
 53     x=rand()%xmax+1;
 54     y=rand()%ymax+1;
 55     while(snake_map[x][y]!=' ')
 56     {
 57         srand((unsigned)time(NULL));
 58         x=rand()%xmax+1;
 59         y=rand()%ymax+1;
 60     }
 61     snake_map[x][y]='@';
 62 }
 63 void snake_insertbody()
 64 {
 65     struct snake_body *node = (struct snake_body *)malloc(sizeof(struct snake_body));
 66     node->if_fist = 1;
 67     node->x=head.x;
 68     node->y=head.y;
 69     node->next=head.first_body;
 70     node->next->if_fist= 0 ;
 71     node->pre=NULL;
 72     head.first_body->pre=node;
 73     head.first_body=node;
 74 }
 75 void snake_delbody()
 76 {
 77     struct snake_body *node = (struct snake_body *)malloc(sizeof(struct snake_body));
 78     node = head.last_body;
 79     head.last_body = head.last_body->pre;
 80     head.last_body->next=NULL;
 81     free(node);
 82     snake_map[node->x][node->y]=' ';
 83 }
 84 void snake_redraw()
 85 {
 86     struct snake_body *temp = head.first_body;
 87     snake_map[head.x][head.y]=head.direct;
 88     while (temp->next!=NULL)
 89     {
 90         snake_map[temp->x][temp->y]='#';
 91         temp=temp->next;
 92     }
 93 }
 94 void snake_body_clean()
 95 {
 96     struct snake_body *temp = head.first_body;
 97     snake_map[head.x][head.y]=head.direct;
 98     while (temp->next!=NULL)
 99     {
100         temp=temp->next;
101         if(temp->pre)
102             free(temp->pre);        
103     }
104 
105 }
106 int snake_move()
107 {
108     char direct = head.direct;
109     int x=head.x;
110     int y=head.y;
111 
112     switch (direct)
113     {
114     case 'A':
115         x=x-1;
116         break;
117     case 'V':
118         x=x+1;
119         break;
120     case '>':
121         y=y+1;
122         break;
123     default:
124         y=y-1;
125         break;
126     }
127     if(x<1 || x>MAP_X_LEN-2)
128         return 2;
129     if(y<1 || y>MAP_Y_LEN-2)
130         return 2;
131 
132     if(snake_map[x][y]!='@')
133         snake_delbody();
134     else
135     {
136         head.len++;
137         make_apple();
138     }
139     if(snake_map[x][y]== '*' || snake_map[x][y]== '#')
140         return 1;
141     
142     snake_insertbody();
143     head.x=x;
144     head.y=y;
145     snake_redraw();
146 
147     
148     head.keepdir = head.direct;
149     return 0;
150 }
151 void snake_init()
152 {
153     int x,y;
154     int direct;
155     struct snake_body *fist = (struct snake_body *)malloc(sizeof(struct snake_body));
156     struct snake_body *last = (struct snake_body *)malloc(sizeof(struct snake_body));
157 
158     srand((unsigned)time(NULL));
159     x=rand()%10+10; 
160     y=rand()%50+25;
161     head.x=x;
162     head.y=y;
163     head.first_body=fist;
164     head.last_body=last;
165     head.len=0;
166 
167     fist->if_fist=1;
168     last->if_fist=0;
169     fist->next=last;
170     fist->pre=NULL;
171     last->next=NULL;
172     last->pre=fist;
173 
174     direct=rand()%4;
175     switch (direct)
176     {
177     case 0:
178         head.direct='V';
179         head.keepdir='V';
180         fist->x=x-1;
181         fist->y=y;
182         last->x=x-2;
183         last->y=y;
184         break;
185     case 1:
186         head.direct='<';
187         head.keepdir='<';
188         fist->x=x;
189         fist->y=y+1;
190         last->x=x;
191         last->y=y+2;
192         break;
193     case 2:
194         head.direct='>';
195         head.keepdir='>';
196         fist->x=x;
197         fist->y=y-1;
198         last->x=x;
199         last->y=y-2;
200         break;
201     default:
202         head.direct='A';
203         head.keepdir='A';
204         fist->x=x+1;
205         fist->y=y;
206         last->x=x+2;
207         last->y=y;    
208         break;
209     }
210     snake_redraw();
211 }
212 
213 void get_key()
214 {
215     char ch,ch1;
216     char direct = head.direct;
217 
218     //new_direct=direct;
219     //printf("\r Get key %c! \n",ch);
220     ch=getchar();
221     sum_get++;
222     
223     if(ch == 27)
224         if(getchar()=='[')
225         {
226             ch1=getchar();
227             if(ch1=='A')
228                 ch='8';
229             if(ch1=='B')
230                 ch='5';
231             if(ch1=='C')
232                 ch='6';
233             if(ch1=='D')
234                 ch='4';
235         }
236     switch (ch)
237     {
238     case '8':;
239     case 'W':;
240     case 'w':
241         if(head.keepdir != 'V') //direct!='V')
242         {
243             head.direct='A';
244             
245         }
246         break;
247     case 's':;
248     case '5':;
249     case 'S':
250         if(head.keepdir !='A')//direct!='A')
251         {
252             head.direct='V';
253             
254         }
255         break;
256     case 'a':;
257     case '4':;
258     case 'A':
259         if(head.keepdir !='>')//direct!='>')
260         {
261             head.direct='<';
262             
263         }
264         break;
265     case 'd':;
266     case '6':;
267     case 'D':
268         if(head.keepdir !='<')//direct!='<')
269         {
270             head.direct='>';
271             
272         }
273         break;
274     case 'p':
275         if(control==2)
276             control=1;
277         else
278             control=2;
279         break;
280     case 'x':
281         control = 0;
282         break;
283 
284     default:
285         break;
286     }
287 }
288 
289 
290 
291 void map_init(int x)
292 {
293     int i;
294     if(x>=MAP_X_LEN)
295         return;
296     if(x == 0 || x == MAP_X_LEN-1)
297     {
298         for(i=0;i<MAP_Y_LEN;i++)
299             snake_map[x][i] = '*';
300     }
301     else
302     {
303         for(i=0;i<MAP_Y_LEN;i++)
304             snake_map[x][i] = ' ';
305         snake_map[x][0] = '*';
306         snake_map[x][MAP_Y_LEN-1] = '*';
307     }
308 }
309 
310 void map_draw()
311 {
312     int i,j;
313     if(control==1)
314         printf("\r\033[32mRUN..........   \033[0mTIME:%d   SCORE:%d  || KEEP_DIRECT:%c , DIRECT:%c , SUM_GET:%d \n",sum_sec/2,head.len,head.keepdir,head.direct,sum_get);
315     else if(control==2)
316         printf("\r\033[33mPAUSE........   \033[0mTIME:%d   SCORE:%d  \n",sum_sec/2,head.len);
317     for(i=0;i<MAP_X_LEN;i++)
318         for(j=0;j<MAP_Y_LEN;j++)
319         {
320             if(j == 0)
321                 printf("\r");
322             printf("%c",snake_map[i][j]);
323             if(j == MAP_Y_LEN-1)
324                 printf("\n");
325         }
326 
327     printf("\033[31A");
328 }
329 void map_clean()
330 {
331     int i,j;
332     printf("\n");
333     for(i=0;i<MAP_X_LEN;i++)
334         for(j=0;j<MAP_Y_LEN;j++)
335         {
336             if(j == 0)
337                 printf("\r");
338             printf(" ");
339             if(j == MAP_Y_LEN-1)
340                 printf("\n");
341         }
342         printf("\033[30A");
343 }
344 
345 int set_timer(int n_us)
346 {
347     signal(SIGALRM, timer_do);
348     struct itimerval tick;
349     tick.it_value.tv_sec=0;
350     tick.it_value.tv_usec=n_us;
351 
352     tick.it_interval.tv_sec=0;
353     tick.it_interval.tv_usec=n_us;
354     return setitimer(ITIMER_REAL, &tick, NULL);
355 }
356 
357 void timer_do()
358 {
359     int i;
360     //head.direct = new_direct;
361     if(control<2)
362     {
363         
364         i=snake_move();
365         if(i)
366         {
367             control = 0;
368             set_timer(0); 
369             printf("\r\033[31mGAME OVER....   \033[0mTIME:%d   SCORE:%d  || N_DIRECT:%c , DIRECT:%c , SUM_GET:%d \n",sum_sec/2,head.len,new_direct,head.direct,sum_get);
370         }    
371         else;
372         map_draw();
373     }
374     else
375         map_draw();
376     
377     sum_sec++;
378 }
379 
380 void control_init()
381 {
382     int res;
383 
384     initscr();
385     raw();
386     noecho();
387     control=1;
388     sum_sec=0;
389     printf("\033[?25l");
390     //signal(SIGIO,get_key);
391     //fcntl(STDIN_FILENO,F_SETOWN,getpid());
392     //fcntl(STDIN_FILENO,F_SETFL, fcntl(STDIN_FILENO,F_GETFL) | O_ASYNC);
393     if(set_timer(le*10000))
394     {
395         printf("SET TIMER FAILED \n");
396         control=0;
397     }
398 
399 }
400 void control_exit()
401 {
402     endwin();
403     printf("\033[?25h");
404 }
405 void list_draw()
406 {
407     char str[5][50] = {"CMD 1 : RESTART (WITHOUT SELECT LEVEL)            ",
408                        "CMD 2 : RESTART (SELECT NEW LEVEL)                ",
409                        "CMD x : EXIT                                      ",
410                        "CMD 3 : NOTING TO DO                              ",
411                        "CMD 4 : NOTING TO DO                              "};
412                      // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
413     int i,j,N_CMD=5;
414 
415     for(i=1;i<MAP_X_LEN-1;i++)
416         for(j=1;j<MAP_Y_LEN-1;j++)
417             snake_map[i][j] = ' ';
418 
419     for(i=0;i<N_CMD;i++)
420     {
421         for(j=0;j<49;j++)
422         {
423             snake_map[3*i+5][j+5]=str[i][j];
424 
425         }
426         
427         usleep(200000);
428         printf("\n");
429         map_draw();
430     }
431 
432 
433 }
434 void list_select()
435 {
436     char ch;
437     int i;
438 
439     
440 
441     list_draw();
442 
443     printf("\033[2A");
444 
445 donothing:
446     
447     for(i=0;i<MAP_Y_LEN;i++)
448         printf(" ");
449     printf("\rSELECT CMD .......");
450     ch = getchar();
451     switch (ch)
452     {
453     case '1'://restart
454         control_exit();
455         snake_body_clean();
456         snake_init();
457         restart=1;
458         //printf("\033[1A");
459         break;
460     case '2'://restart
461         control_exit();
462         snake_body_clean();
463         snake_init();
464         restart=1;
465         ifselectle = 1;
466         printf("\033[1A");
467         break;
468     case 'X':;
469     case 'x':
470         control_exit();
471         snake_body_clean();
472         printf("\033[31B");
473         break;
474     default:
475         //printf("\n\033[2A");
476         //printf("\033[u");
477         goto donothing;
478         break;
479     }
480     printf("\n");
481 }
482 
483 int main()
484 {
485     int fd = 0,err = 0,i,j;
486     unsigned long cmd; //与底层驱动使用相同的定义  此处使用int应该也是可以的
487     int *arg ; //这里底层命令使用的是地址 所以这里也是地址 个人认为地址传送与内核写法比较一致
488     int argint = 0;
489     char progress_bar[101],background_bar[101];//需要绘制的进度条和进度条的背景
490   
491     char level;
492 
493     for(i=0;i<101;i++) //进度条初始化  101是用来保证progress_bar的队尾不被输出
494     {
495         progress_bar[i] = 0;
496         background_bar[i] = ' ';
497     }
498 
499     //进度条没什么作用,就是为了好看
500     for(i=1;i<=100;i++)//循环打印   //这种方式绘制进度条思路比较简单
501     {
502         progress_bar[i-1] = ' ';
503         background_bar[100-i] = 0;
504 
505         printf("\033[?25lSET UP %3d%% \033[42m%s\033[47m%s\033[0m\r",
506             i,progress_bar,background_bar);//绘制进度条 //格式控制,优化访问缓冲区的次数
507         
508 
509         fflush(stdout);//清空输出缓冲区
510         usleep(10000);
511     }
512     printf("SET UP DONE\n");
513     
514     
515 while(restart)
516 {
517   restart=0;
518   for (i = 0; i < MAP_X_LEN; i++)
519         {
520             map_init(i);
521         }
522 
523     printf("CHOOSE LEVEL(1-100):");
524 
525     if(ifselectle)
526     {
527         scanf("%d",&le);
528         //printf("\033[1A");
529         ifselectle=0;
530         if(le<1) 
531             le=1;
532         else if(le>100) 
533             le=100;
534     }
535 
536     snake_init();
537     make_apple();
538     control_init();
539 
540 
541     while(control)
542     {
543         get_key();
544     }
545     
546     list_select();
547     
548     //map_clean(); 
549     
550     
551 }
552 return 0;
553 }

 

posted @ 2016-08-09 14:09  吃猫粮的耗子  阅读(403)  评论(0)    收藏  举报