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
- #ifndef __CHAOS_H__
- #define __CHAOS_H__
- extern void chaos_lorenz(char *result);
- #endif
chaos.c
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <malloc.h>
- #include <time.h>
- #include <sys/time.h>
- #include "chaos.h"
- void chaos_lorenz(char *result)
- {
- int i;
- int j=20;
- float x[2],y[2],z[2];
- float a=10,b=8/3,c=28;
- float t=0.01;
- struct timeval tv;
- struct timezone tz;
- gettimeofday (&tv , &tz);
- x[0]=0.1;
- y[0]=0.1;
- z[0]=0.1;
- for(i=0;i<tv.tv_usec%1000+j;i++)
- {
- x[1]=x[0]+t*(a*(y[0]-x[0]));
- y[1]=y[0]+t*(c*x[0]-y[0]-x[0]*z[0]);
- z[1]=z[0]+t*(x[0]*y[0]-b*z[0]);
- x[0]=x[1];
- y[0]=y[1];
- z[0]=z[1];
- }
- sprintf(result,"%6.4f&%6.4f&%6.4f",x[0],y[0],z[0]);
- //printf("%s\n",result);
- }
list.h
- #ifndef __LIST_H__
- #define __LIST_H__
- #ifdef __cplusplus
- extern "C"{
- #endif
- typedef enum _dListRet
- {
- DLIST_RET_OK,
- DLIST_RET_OOM,
- DLIST_RET_PARAMS,
- DLIST_RET_STOP,
- DLIST_RET_FAIL
- }dListRet;
- struct direct
- {
- int cx;
- int cy;
- };
- struct _node
- {
- int cx;
- int cy;
- struct _node *prev;
- struct _node *next;
- };
- typedef struct _node node;
- struct _dList
- {
- node *head;
- node *tail;
- };
- typedef struct _dList dList;
- extern dList* list_create(void);
- extern dListRet add_node_after_head(dList *thiz, int x, int y);
- extern dListRet delete_node_before_tail(dList *thiz);
- extern dListRet delete_list(dList *thiz);
- #ifdef __cplusplus
- }
- #endif
- #endif
list.c
- #include <stdio.h>
- #include <stdlib.h>
- #include "list.h"
- dList* list_create(void)
- {
- dList *thiz =(dList *)malloc(sizeof(dList));
- node *temp = (node *)malloc(sizeof(node));
- thiz->head =(node *)malloc(sizeof(node));
- thiz->tail =(node *)malloc(sizeof(node));
- if(temp != NULL)
- {
- temp->cx = 5;
- temp->cy = 10;
- }
- if(thiz != NULL && temp != NULL)
- {
- thiz->head->prev = thiz->tail->next = NULL;
- thiz->head->next = temp;
- thiz->tail->prev = temp;
- temp->prev = thiz->head;
- temp->next = thiz->tail;
- }
- return thiz;
- }
- dListRet add_node_after_head(dList *thiz, int x, int y)
- {
- node *temp = (node *)malloc(sizeof(node));
- if(temp != NULL)
- {
- temp->cx = x;
- temp->cy = y;
- temp->prev = thiz->head;
- temp->next = thiz->head->next;
- temp->next->prev = temp;
- thiz->head->next = temp;
- /*2
- temp->prev = thiz->head;
- temp->next = thiz->head->next;
- thiz->head->next = temp;
- thiz->head->next->next->prev = temp;
- */
- /*3
- thiz->head->next->prev =temp;
- temp->prev = thiz->head;
- temp->next = thiz->head->next->next;
- thiz->head->next = temp;
- */
- }
- return DLIST_RET_OK;
- }
- dListRet delete_node_before_tail(dList *thiz)
- {
- node *temp = thiz->tail->prev;
- node *btemp = temp->prev;
- btemp->next = thiz->tail;
- thiz->tail->prev = btemp;
- free(temp);
- return DLIST_RET_OK;
- }
- dListRet delete_list(dList *thiz)
- {
- while(thiz->head->next != thiz->tail)
- {
- delete_node_before_tail(thiz);
- }
- free(thiz->head);
- free(thiz->tail);
- free(thiz);
- return DLIST_RET_OK;
- }
snake.c
- #include <stdio.h>
- #include <stdlib.h>
- #include <curses.h>
- #include <signal.h>
- #include <sys/time.h>
- #include <time.h>
- #include <assert.h>
- #include <math.h>
- #include "list.h"
- #include "chaos.h"
- #define NUM 60
- void init_screen();
- int setTicker(long n_msec);
- void food_gen();
- void init_game();
- void show();
- void getDir();
- void over(int i);
- int hour,minute,second;
- int tTime,length,level;
- struct direct dir,food;
- dList *list;
- int main(void)
- {
- init_game();
- signal(SIGALRM, show);
- getDir();
- endwin();
- return 0;
- }
- void init_screen()
- {
- initscr();
- cbreak();
- //nonl();
- noecho();
- curs_set(0);
- //intrflush(stdscr,FALSE);
- keypad(stdscr,TRUE);
- //refresh();
- }
- void food_gen()
- {
- char *result;
- float x,y,z;
- int m,n,k;
- time_t now;
- now = time(0);
- struct tm *tnow = localtime(&now);
- result=(char *)malloc(100);
- if(!result)
- {
- fprintf(stderr, "malloc failed!\n");
- }
- chaos_lorenz(result);
- sscanf(result,"%f&%f&%f",&x,&y,&z);
- free(result);
- m=((int)(fabs(x)*1000))&0xffff;
- n=((int)(fabs(y)*1000))&0xffff;
- k=((int)(fabs(z)*1000))&0xffff;
- int htime = tnow->tm_year+tnow->tm_mon+1+tnow->tm_mday;
- int ltime = tnow->tm_hour+tnow->tm_min+tnow->tm_sec;
- food.cx = (m+ltime%1000+htime%1000) % COLS;
- food.cy = (n+ltime%1000+htime%1000) % (LINES-2) + 2;
- }
- void init_game()
- {
- init_screen();
- hour = minute = second = 0;
- tTime = 0;
- length = 1;
- level = 0;
- dir.cx = 1;
- dir.cy = 0;
- food_gen();
- /*
- srand(time(0));
- food.cx = rand() % COLS;
- food.cy = rand() % (LINES-2) + 2;
- */
- list=list_create();
- setTicker(20);
- }
- int setTicker(long n_msec)
- {
- struct itimerval new_timerset;
- long n_sec;
- long n_usec;
- n_sec = n_msec/1000;
- n_usec = (n_msec%1000)*1000L;
- new_timerset.it_interval.tv_sec = n_sec;
- new_timerset.it_interval.tv_usec = n_usec;
- n_msec = 1;
- n_sec = n_msec/1000;
- n_usec = (n_msec%1000)*1000L;
- new_timerset.it_value.tv_sec = n_sec;
- new_timerset.it_value.tv_usec = n_usec;
- return setitimer(ITIMER_REAL,&new_timerset,NULL);
- }
- void showInformation()
- {
- int i;
- tTime++;
- if(tTime >= 1000000)
- tTime = 0;
- if(1 != tTime % 50) //50*20ms=1000ms
- return;
- //清屏并显示分隔符
- move(0, 0);
- for(i=0;i<COLS;i++)
- addstr(" ");
- move(1, 0);
- for(i=0;i<COLS;i++)
- addstr("-");
- //显示时间
- move(0, 3);
- printw("time: %d:%d:%d %c", hour, minute, second);
- second++;
- if(second >= NUM)
- {
- second = 0;
- minute++;
- }
- if(minute >= NUM)
- {
- minute = 0;
- hour++;
- }
- //显示长度,等级
- move(0, COLS/2-5);
- printw("length: %d", length);
- move(0, COLS-10);
- level = length / 3 + 1;
- printw("level: %d", level);
- }
- void showSnake()
- {
- if(1 != tTime % (30-level))
- return;
- //判断蛇的长度有没有改变
- bool lenChange = false;
- //显示食物
- move(food.cy, food.cx);
- printw("{1}quot;);
- //如果蛇碰到墙,则游戏结束
- if((COLS-1==list->head->next->cx && 1==dir.cx)
- || (0==list->head->next->cx && -1==dir.cx)
- || (LINES-1==list->head->next->cy && 1==dir.cy)
- || (2==list->head->next->cy && -1==dir.cy))
- {
- over(1);
- return;
- }
- //如果蛇头砬到自己的身体,则游戏结束
- if('*' == mvinch(list->head->next->cy+dir.cy, list->head->next->cx+dir.cx) )
- {
- over(2);
- return;
- }
- assert(add_node_after_head(list,list->head->next->cx+dir.cx,list->head->next->cy+dir.cy)==DLIST_RET_OK);
- //蛇吃了一个“食物”
- if(list->head->next->cx==food.cx && list->head->next->cy==food.cy)
- {
- lenChange = true;
- length++;
- //恭喜你,通关了
- if(length >= 50)
- {
- over(3);
- return;
- }
- //重新设置食物的位置
- food_gen();
- /*
- food.cx = rand() % COLS;
- food.cy = rand() % (LINES-2) + 2;
- */
- }
- if(!lenChange)
- {
- move(list->tail->prev->cy, list->tail->prev->cx);
- printw(" ");
- assert(delete_node_before_tail(list)==DLIST_RET_OK);
- }
- move(list->head->next->cy, list->head->next->cx);
- printw("*");
- }
- void show()
- {
- signal(SIGALRM, show);
- showInformation();
- showSnake();
- refresh();
- };
- void getDir()
- {
- int ch;
- while(1)
- {
- ch=getch();
- switch(ch)
- {
- case KEY_LEFT:
- dir.cx = -1;
- dir.cy = 0;
- break;
- case KEY_UP:
- dir.cx = 0;
- dir.cy = -1;
- break;
- case KEY_RIGHT:
- dir.cx = 1;
- dir.cy = 0;
- break;
- case KEY_DOWN:
- dir.cx = 0;
- dir.cy = 1;
- break;
- case 27:
- setTicker(0); //关闭计时器
- delete_list(list);
- endwin();
- exit(0);
- default:;
- }
- setTicker(20);
- }
- }
- void over(int i)
- {
- int j;
- //separator
- move(LINES-2, 0);
- for(j=0;j<COLS;j++)
- addstr("-");
- //Exit information
- move(LINES-3, 0);
- for(j=0;j<COLS;j++)
- addstr(" ");
- move(LINES-3,0);
- switch(i)
- {
- case 1:
- addstr("Crash the wall! Game over.");
- break;
- case 2:
- addstr("Crash itself! Game over");
- break;
- case 3:
- addstr("Mission Complete!");
- break;
- default:;
- }
- setTicker(0); //关闭计时器
- delete_list(list); //释放链表的空间
- //Tips
- move(LINES-1, 0);
- for(j=0;j<COLS;j++)
- addstr(" ");
- move(LINES-1, 0);
- addstr("Tips : Please enter any key to quit.");
- getch();
- endwin();
- exit(1);
- }
Makefile
- test:snake.c list.c chaos.c
- gcc -g snake.c list.c chaos.c -o snake -lcurses
- clean:
- rm snake
- distclean:
- 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
- [荐]Linux C编程连载(6)- “混沌”贪吃蛇
- Linux C编程连载【6】- “混沌”贪吃蛇
- Linux C编程连载(3)-串口编程
- Linux C编程连载【3】-串口编程
- 《 Linux C编程一站式学习》连载一
- 《 Linux C编程一站式学习》连载二
- 《 Linux C编程一站式学习》连载三
- 《 Linux C编程一站式学习》连载四
- 《 Linux C编程一站式学习》连载五
- 《 Linux C编程一站式学习》连载六
- 《 Linux C编程一站式学习》连载七
- 《 Linux C编程一站式学习》连载八
- 《 Linux C编程一站式学习》连载九
- 《 Linux C编程一站式学习》连载十
- 《 Linux C编程一站式学习》连载十一
- 《 Linux C编程一站式学习》连载十二
- 《 Linux C编程一站式学习》连载十三
- Linux C编程连载(2)-鼠标控制
- 网页开发如何弹出式文本(密码)输入框
- 嵌入式硬件平台接口开发
- 在项目中添加自己的代码注释
- Linux C编程连载【5】- 关于双链表“掉链子”的问题
- copy_from_user 详解
- Linux C编程连载【6】- “混沌”贪吃蛇
- Emacs 中的 auto-mode-alist 正则式 解释
- oracle分析函数
- 工厂模式-参观者模式
- 泛型集合
- imx53 uboot tftp nfs启动, linux tftp,复制gdb, linux host 创建sd卡启动,ddr stress tester
- 一步一步写算法(之创建逆序链表)
- vc IDE 环境乱导致的问题 ifstream binary 出错问题解决
- pctfree,IniTrans,maxtrans