Linux C编程连载【6】- “混沌”贪吃蛇

来源:互联网 发布:c语言warning 编辑:程序博客网 时间:2024/05/11 01:43

【任务】利用混沌随机数实现贪吃蛇游戏。

【解析】

【分析】

(1) 采用Lorenz 混沌映射                                           

       根据混沌时间序列的非周期性,改变迭代次数则会产生伪随机的运算结果。将时间(微秒) 向正的方向平移j(j>0),作为Lorenz映射的迭代因子,则迭代次数的范围为[j,j+1000],则混沌方程最少进行j次迭代,最多进行j+1000次迭代。将迭代的序列进行映射处理与本地时间组合,则可以形成随机且唯一的序列码。该序列码可以作为贪吃蛇食物的种子。

(2) 贪吃蛇实现

       贪吃蛇是双链表的典型操作。初始化的贪吃蛇为一个具有3个节点的双链表,包括head,tail和temp节点。

游戏开始后,首先在贪吃蛇头结点之后插入一个新节点,如果贪吃蛇没有吃到食物,就删除掉尾节点之前的一个节点。这样只要在相当短的时间内进行(如20ms),利用人眼的视觉暂留,就会显示出贪吃蛇移动的效果。如果贪吃蛇吃到了食物,就不删除新插入的节点,并显示这个节点的内容(蛇身)。贪吃蛇实现效果如图1所示:

图1 贪吃蛇实现效果

 

chaos.h

view plain
  1. #ifndef __CHAOS_H__  
  2. #define __CHAOS_H__  
  3.   
  4. extern void chaos_lorenz(char *result);  
  5.   
  6. #endif  

chaos.c

view plain
  1. #include <stdlib.h>  
  2. #include <stdio.h>  
  3. #include <string.h>  
  4. #include <malloc.h>  
  5. #include <time.h>  
  6. #include <sys/time.h>  
  7. #include "chaos.h"  
  8.   
  9. void chaos_lorenz(char *result)  
  10. {  
  11.     int i;  
  12.     int j=20;  
  13.   
  14.     float x[2],y[2],z[2];  
  15.     float a=10,b=8/3,c=28;  
  16.     float t=0.01;  
  17.   
  18.     struct timeval tv;  
  19.     struct timezone tz;  
  20.     gettimeofday (&tv , &tz);  
  21.   
  22.     x[0]=0.1;  
  23.     y[0]=0.1;  
  24.     z[0]=0.1;  
  25.   
  26.     for(i=0;i<tv.tv_usec%1000+j;i++)  
  27.     {  
  28.         x[1]=x[0]+t*(a*(y[0]-x[0]));  
  29.         y[1]=y[0]+t*(c*x[0]-y[0]-x[0]*z[0]);  
  30.         z[1]=z[0]+t*(x[0]*y[0]-b*z[0]);  
  31.   
  32.         x[0]=x[1];  
  33.         y[0]=y[1];  
  34.         z[0]=z[1];  
  35.     }  
  36.       
  37.     sprintf(result,"%6.4f&%6.4f&%6.4f",x[0],y[0],z[0]);  
  38.     //printf("%s\n",result);  
  39. }  

list.h

view plain
  1. #ifndef __LIST_H__  
  2. #define __LIST_H__  
  3.   
  4. #ifdef __cplusplus  
  5. extern "C"{  
  6. #endif  
  7.   
  8. typedef enum _dListRet  
  9. {  
  10.     DLIST_RET_OK,  
  11.     DLIST_RET_OOM,  
  12.     DLIST_RET_PARAMS,  
  13.     DLIST_RET_STOP,  
  14.     DLIST_RET_FAIL  
  15. }dListRet;  
  16.   
  17. struct direct  
  18. {  
  19.     int cx;  
  20.     int cy;  
  21. };  
  22.   
  23. struct _node  
  24. {  
  25.     int cx;  
  26.     int cy;  
  27.     struct _node *prev;  
  28.     struct _node *next;  
  29. };  
  30.   
  31. typedef struct _node node;  
  32.   
  33. struct _dList  
  34. {  
  35.     node *head;  
  36.     node *tail;  
  37. };  
  38. typedef struct _dList dList;  
  39.   
  40.   
  41. extern dList* list_create(void);  
  42. extern dListRet add_node_after_head(dList *thiz, int x, int y);  
  43. extern dListRet delete_node_before_tail(dList *thiz);  
  44. extern dListRet delete_list(dList *thiz);  
  45.   
  46. #ifdef __cplusplus  
  47. }  
  48. #endif  
  49.   
  50. #endif  

list.c

view plain
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include "list.h"  
  4.   
  5. dList* list_create(void)  
  6. {  
  7.     dList *thiz =(dList *)malloc(sizeof(dList));  
  8.     node *temp = (node *)malloc(sizeof(node));  
  9.   
  10.     thiz->head =(node *)malloc(sizeof(node));  
  11.     thiz->tail =(node *)malloc(sizeof(node));  
  12.   
  13.     if(temp != NULL)  
  14.     {  
  15.         temp->cx = 5;  
  16.         temp->cy = 10;  
  17.     }  
  18.   
  19.     if(thiz != NULL && temp != NULL)  
  20.     {  
  21.         thiz->head->prev = thiz->tail->next = NULL;  
  22.         thiz->head->next = temp;  
  23.         thiz->tail->prev = temp;  
  24.         temp->prev = thiz->head;  
  25.         temp->next = thiz->tail;  
  26.     }  
  27.     return thiz;  
  28. }  
  29.   
  30. dListRet add_node_after_head(dList *thiz, int x, int y)  
  31. {  
  32.     node *temp = (node *)malloc(sizeof(node));  
  33.   
  34.     if(temp != NULL)  
  35.     {  
  36.         temp->cx = x;  
  37.         temp->cy = y;  
  38.           
  39.           
  40.         temp->prev = thiz->head;  
  41.         temp->next = thiz->head->next;  
  42.         temp->next->prev = temp;  
  43.         thiz->head->next = temp;  
  44.           
  45.   
  46.         /*2  
  47.         temp->prev = thiz->head;  
  48.         temp->next = thiz->head->next;  
  49.         thiz->head->next = temp;  
  50.         thiz->head->next->next->prev = temp;  
  51.         */  
  52.   
  53.         /*3  
  54.         thiz->head->next->prev =temp;  
  55.         temp->prev = thiz->head;  
  56.         temp->next = thiz->head->next->next;  
  57.         thiz->head->next = temp;  
  58.         */  
  59.     }  
  60.   
  61.     return DLIST_RET_OK;  
  62. }  
  63.   
  64. dListRet delete_node_before_tail(dList *thiz)  
  65. {  
  66.     node *temp = thiz->tail->prev;  
  67.         node *btemp = temp->prev;  
  68.     btemp->next = thiz->tail;  
  69.     thiz->tail->prev = btemp;  
  70.     free(temp);  
  71.     return DLIST_RET_OK;  
  72. }  
  73.   
  74. dListRet delete_list(dList *thiz)  
  75. {  
  76.     while(thiz->head->next != thiz->tail)  
  77.     {  
  78.         delete_node_before_tail(thiz);  
  79.     }  
  80.     free(thiz->head);  
  81.     free(thiz->tail);  
  82.     free(thiz);  
  83.     return DLIST_RET_OK;  
  84. }  


snake.c

view plain
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <curses.h>  
  4. #include <signal.h>  
  5. #include <sys/time.h>  
  6. #include <time.h>  
  7. #include <assert.h>  
  8. #include <math.h>  
  9. #include "list.h"  
  10. #include "chaos.h"  
  11.   
  12. #define NUM 60  
  13.   
  14. void init_screen();  
  15. int setTicker(long n_msec);  
  16. void food_gen();  
  17. void init_game();  
  18. void show();  
  19. void getDir();  
  20. void over(int i);  
  21.   
  22. int hour,minute,second;  
  23. int tTime,length,level;  
  24. struct direct dir,food;  
  25. dList *list;  
  26.   
  27. int main(void)  
  28. {  
  29.     init_game();  
  30.     signal(SIGALRM, show);  
  31.         getDir();  
  32.     endwin();  
  33.     return 0;  
  34. }  
  35.   
  36. void init_screen()  
  37. {  
  38.     initscr();  
  39.     cbreak();   
  40.     //nonl();   
  41.     noecho();  
  42.     curs_set(0);  
  43.     //intrflush(stdscr,FALSE);   
  44.     keypad(stdscr,TRUE);   
  45.     //refresh();  
  46. }  
  47.   
  48. void food_gen()  
  49. {  
  50.     char *result;  
  51.     float x,y,z;  
  52.     int m,n,k;  
  53.     time_t now;  
  54.     now = time(0);  
  55.     struct tm *tnow = localtime(&now);  
  56.   
  57.     result=(char *)malloc(100);  
  58.     if(!result)  
  59.     {  
  60.         fprintf(stderr, "malloc failed!\n");  
  61.     }  
  62.     chaos_lorenz(result);  
  63.     sscanf(result,"%f&%f&%f",&x,&y,&z);  
  64.     free(result);  
  65.   
  66.     m=((int)(fabs(x)*1000))&0xffff;       
  67.     n=((int)(fabs(y)*1000))&0xffff;  
  68.     k=((int)(fabs(z)*1000))&0xffff;  
  69.       
  70.     int htime = tnow->tm_year+tnow->tm_mon+1+tnow->tm_mday;  
  71.     int ltime = tnow->tm_hour+tnow->tm_min+tnow->tm_sec;  
  72.     food.cx = (m+ltime%1000+htime%1000) % COLS;  
  73.         food.cy = (n+ltime%1000+htime%1000) % (LINES-2) + 2;  
  74. }  
  75.   
  76. void init_game()  
  77. {  
  78.     init_screen();  
  79.     hour = minute = second = 0;  
  80.     tTime = 0;  
  81.     length = 1;  
  82.     level = 0;  
  83.     dir.cx = 1;  
  84.     dir.cy = 0;  
  85.     food_gen();  
  86.     /*  
  87.     srand(time(0));  
  88.     food.cx = rand() % COLS;  
  89.         food.cy = rand() % (LINES-2) + 2;  
  90.     */  
  91.     list=list_create();  
  92.     setTicker(20);  
  93. }  
  94.   
  95. int setTicker(long n_msec)  
  96. {  
  97.     struct itimerval new_timerset;  
  98.     long n_sec;  
  99.     long n_usec;  
  100.     n_sec = n_msec/1000;  
  101.     n_usec = (n_msec%1000)*1000L;  
  102.     new_timerset.it_interval.tv_sec = n_sec;  
  103.     new_timerset.it_interval.tv_usec = n_usec;  
  104.     n_msec = 1;  
  105.     n_sec = n_msec/1000;  
  106.     n_usec = (n_msec%1000)*1000L;  
  107.     new_timerset.it_value.tv_sec = n_sec;  
  108.     new_timerset.it_value.tv_usec = n_usec;  
  109.     return setitimer(ITIMER_REAL,&new_timerset,NULL);  
  110. }  
  111.   
  112. void showInformation()  
  113. {  
  114.     int i;  
  115.     tTime++;  
  116.     if(tTime >= 1000000)  
  117.         tTime = 0;  
  118.     if(1 != tTime % 50) //50*20ms=1000ms  
  119.         return;  
  120.       
  121.     //清屏并显示分隔符  
  122.     move(0, 0);  
  123.     for(i=0;i<COLS;i++)  
  124.         addstr(" ");  
  125.   
  126.     move(1, 0);  
  127.     for(i=0;i<COLS;i++)  
  128.         addstr("-");  
  129.   
  130.     //显示时间  
  131.     move(0, 3);   
  132.     printw("time: %d:%d:%d %c", hour, minute, second);  
  133.         second++;  
  134.   
  135.     if(second >= NUM)  
  136.     {  
  137.         second = 0;  
  138.         minute++;  
  139.     }  
  140.     if(minute >= NUM)  
  141.     {  
  142.         minute = 0;  
  143.         hour++;  
  144.     }  
  145.     //显示长度,等级  
  146.     move(0, COLS/2-5);  
  147.     printw("length: %d", length);  
  148.     move(0, COLS-10);  
  149.     level = length / 3 + 1;  
  150.     printw("level: %d", level);  
  151. }  
  152.   
  153. void showSnake()  
  154. {  
  155.     if(1 != tTime % (30-level))  
  156.         return;  
  157.     //判断蛇的长度有没有改变  
  158.     bool lenChange = false;  
  159.     //显示食物  
  160.     move(food.cy, food.cx);  
  161.     printw("{1}quot;);  
  162.     //如果蛇碰到墙,则游戏结束  
  163.     if((COLS-1==list->head->next->cx && 1==dir.cx)   
  164.     || (0==list->head->next->cx && -1==dir.cx)  
  165.     || (LINES-1==list->head->next->cy && 1==dir.cy)  
  166.     || (2==list->head->next->cy && -1==dir.cy))  
  167.     {  
  168.         over(1);  
  169.         return;  
  170.     }  
  171.   
  172.     //如果蛇头砬到自己的身体,则游戏结束  
  173.     if('*' == mvinch(list->head->next->cy+dir.cy, list->head->next->cx+dir.cx) )  
  174.     {  
  175.         over(2);  
  176.         return;  
  177.     }  
  178.   
  179.     assert(add_node_after_head(list,list->head->next->cx+dir.cx,list->head->next->cy+dir.cy)==DLIST_RET_OK);  
  180.     //蛇吃了一个“食物”  
  181.     if(list->head->next->cx==food.cx && list->head->next->cy==food.cy)  
  182.     {  
  183.         lenChange = true;  
  184.         length++;  
  185.         //恭喜你,通关了  
  186.         if(length >= 50)  
  187.         {  
  188.             over(3);  
  189.             return;  
  190.         }  
  191.         //重新设置食物的位置  
  192.         food_gen();  
  193.         /*  
  194.         food.cx = rand() % COLS;  
  195.         food.cy = rand() % (LINES-2) + 2;  
  196.         */  
  197.     }  
  198.     if(!lenChange)  
  199.     {  
  200.         move(list->tail->prev->cy, list->tail->prev->cx);  
  201.         printw(" ");  
  202.         assert(delete_node_before_tail(list)==DLIST_RET_OK);  
  203.     }  
  204.   
  205.     move(list->head->next->cy, list->head->next->cx);  
  206.     printw("*");  
  207. }  
  208.   
  209. void show()  
  210. {  
  211.     signal(SIGALRM, show);  
  212.     showInformation();  
  213.     showSnake();  
  214.     refresh();  
  215. };  
  216.   
  217. void getDir()  
  218. {  
  219.     int ch;  
  220.     while(1)  
  221.     {  
  222.         ch=getch();   
  223.         switch(ch)  
  224.         {  
  225.             case KEY_LEFT:  
  226.                 dir.cx = -1;  
  227.                         dir.cy = 0;  
  228.                 break;  
  229.             case KEY_UP:  
  230.                 dir.cx = 0;  
  231.                         dir.cy = -1;  
  232.                 break;  
  233.             case KEY_RIGHT:  
  234.                 dir.cx = 1;  
  235.                         dir.cy = 0;  
  236.                 break;  
  237.             case KEY_DOWN:  
  238.                 dir.cx = 0;  
  239.                         dir.cy = 1;  
  240.                 break;  
  241.             case 27:  
  242.                 setTicker(0);                //关闭计时器  
  243.                 delete_list(list);  
  244.                 endwin();  
  245.                 exit(0);  
  246.             default:;  
  247.         }  
  248.   
  249.         setTicker(20);  
  250.     }  
  251. }  
  252.   
  253. void over(int i)  
  254. {  
  255.     int j;  
  256.     //separator  
  257.     move(LINES-2, 0);  
  258.     for(j=0;j<COLS;j++)  
  259.         addstr("-");  
  260.       
  261.     //Exit information  
  262.     move(LINES-3, 0);  
  263.     for(j=0;j<COLS;j++)  
  264.         addstr(" ");  
  265.     move(LINES-3,0);  
  266.     switch(i)  
  267.     {  
  268.         case 1:  
  269.             addstr("Crash the wall! Game over.");  
  270.             break;  
  271.         case 2:  
  272.             addstr("Crash itself! Game over");  
  273.             break;  
  274.         case 3:  
  275.             addstr("Mission Complete!");  
  276.             break;  
  277.         default:;  
  278.     }  
  279.     setTicker(0);                //关闭计时器  
  280.     delete_list(list);           //释放链表的空间  
  281.       
  282.     //Tips  
  283.     move(LINES-1, 0);  
  284.     for(j=0;j<COLS;j++)  
  285.     addstr(" ");  
  286.     move(LINES-1, 0);  
  287.     addstr("Tips : Please enter any key to quit.");  
  288.     getch();  
  289.     endwin();  
  290.     exit(1);  
  291. }  

Makefile

view plain
  1. test:snake.c list.c chaos.c  
  2.     gcc -g snake.c list.c chaos.c -o snake -lcurses  
  3. clean:  
  4.     rm snake  
  5. distclean:  
  6.     rm snake *~  


【参考】

1 http://blog.csdn.net/tandesir/article/details/6917393

2 http://topic.csdn.net/u/20101001/01/2280b2dd-1446-439d-b1f8-cdd9db1fd615.html

【转载自】http://blog.csdn.net/tandesir/article/details/6954910

原创粉丝点击