|
发表于 2014-2-6 15:22:40
|
显示全部楼层
Linux下代码- #include <stdio.h>
- #include <stdlib.h>
- #include <curses.h>
- #include <signal.h>
- #include <sys/time.h>
- #define NUM 60
- struct direct //用来表示方向的
- {
- int cx;
- int cy;
- };
- typedef struct node //链表的结点
- {
- int cx;
- int cy;
- struct node *back;
- struct node *next;
- }node;
- void initGame(); //初始化游戏
- int setTicker(int); //设置计时器
- void show(); //显示整个画面
- void showInformation(); //显示游戏信息(前两行)
- void showSnake(); //显示蛇的身体
- void getOrder(); //从键盘中获取命令
- void over(int i); //完成游戏结束后的提示信息
- void creatLink(); //(带头尾结点)双向链表以及它的操作
- void insertNode(int x, int y);
- void deleteNode();
- void deleteLink();
- int ch; //输入的命令
- int hour, minute, second; //时分秒
- int length, tTime, level; //(蛇的)长度,计时器,(游戏)等级
- struct direct dir, food; //蛇的前进方向,食物的位置
- node *head, *tail; //链表的头尾结点
- int main()
- {
- initscr();
- initGame();
- signal(SIGALRM, show);
- getOrder();
- endwin();
- return 0;
- }
- void initGame()
- {
- cbreak(); //把终端的CBREAK模式打开
- noecho(); //关闭回显
- curs_set(0); //把光标置为不可见
- keypad(stdscr, true); //使用用户终端的键盘上的小键盘
- srand(time(0)); //设置随机数种子
- //初始化各项数据
- hour = minute = second = tTime = 0;
- length = 1;
- dir.cx = 1;
- dir.cy = 0;
- ch = 'A';
- food.cx = rand() % COLS;
- food.cy = rand() % (LINES-2) + 2;
- creatLink();
- setTicker(20);
- }
- //设置计时器(这个函数是书本上的例子,有改动)
- int setTicker(int n_msecs)
- {
- struct itimerval new_timeset;
- long n_sec, n_usecs;
- n_sec = n_msecs / 1000 ;
- n_usecs = ( n_msecs % 1000 ) * 1000L ;
- new_timeset.it_interval.tv_sec = n_sec;
- new_timeset.it_interval.tv_usec = n_usecs;
- n_msecs = 1;
- n_sec = n_msecs / 1000 ;
- n_usecs = ( n_msecs % 1000 ) * 1000L ;
- new_timeset.it_value.tv_sec = n_sec ;
- new_timeset.it_value.tv_usec = n_usecs ;
- return setitimer(ITIMER_REAL, &new_timeset, NULL);
- }
- void showInformation()
- {
- tTime++;
- if(tTime >= 1000000) //
- tTime = 0;
- if(1 != tTime % 50)
- return;
- 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(1, 0);
- int i;
- for(i=0;i<COLS;i++)
- addstr("-");
- 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("@");
- //如果蛇碰到墙,则游戏结束
- if((COLS-1==head->next->cx && 1==dir.cx)
- || (0==head->next->cx && -1==dir.cx)
- || (LINES-1==head->next->cy && 1==dir.cy)
- || (2==head->next->cy && -1==dir.cy))
- {
- over(1);
- return;
- }
- //如果蛇头砬到自己的身体,则游戏结束
- if('*' == mvinch(head->next->cy+dir.cy, head->next->cx+dir.cx) )
- {
- over(2);
- return;
- }
- insertNode(head->next->cx+dir.cx, head->next->cy+dir.cy);
- //蛇吃了一个“食物”
- if(head->next->cx==food.cx && head->next->cy==food.cy)
- {
- lenChange = true;
- length++;
- //恭喜你,通关了
- if(length >= 50)
- {
- over(3);
- return;
- }
- //重新设置食物的位置
- food.cx = rand() % COLS;
- food.cy = rand() % (LINES-2) + 2;
- }
- if(!lenChange)
- {
- move(tail->back->cy, tail->back->cx);
- printw(" ");
- deleteNode();
- }
- move(head->next->cy, head->next->cx);
- printw("*");
- }
- void show()
- {
- signal(SIGALRM, show); //设置中断信号
- showInformation();
- showSnake();
- refresh(); //刷新真实屏幕
- }
- void getOrder()
- {
- //建立一个死循环,来读取来自键盘的命令
- while(1)
- {
- ch = getch();
- if(KEY_LEFT == ch)
- {
- dir.cx = -1;
- dir.cy = 0;
- }
- else if(KEY_UP == ch)
- {
- dir.cx = 0;
- dir.cy = -1;
- }
- else if(KEY_RIGHT == ch)
- {
- dir.cx = 1;
- dir.cy = 0;
- }
- else if(KEY_DOWN == ch)
- {
- dir.cx = 0;
- dir.cy = 1;
- }
- setTicker(20);
- }
- }
- void over(int i)
- {
- //显示结束原因
- move(0, 0);
- int j;
- for(j=0;j<COLS;j++)
- addstr(" ");
- move(0, 2);
- if(1 == i)
- addstr("Crash the wall. Game over");
- else if(2 == i)
- addstr("Crash itself. Game over");
- else if(3 == i)
- addstr("Mission Complete");
- setTicker(0); //关闭计时器
- deleteLink(); //释放链表的空间
- }
- //创建一个双向链表
- void creatLink()
- {
- node *temp = (node *)malloc( sizeof(node) );
- head = (node *)malloc( sizeof(node) );
- tail = (node *)malloc( sizeof(node) );
- temp->cx = 5;
- temp->cy = 10;
- head->back = tail->next = NULL;
- head->next = temp;
- temp->next = tail;
- tail->back = temp;
- temp->back = head;
- }
- //在链表的头部(非头结点)插入一个结点
- void insertNode(int x, int y)
- {
- node *temp = (node *)malloc( sizeof(node) );
- temp->cx = x;
- temp->cy = y;
- temp->next = head->next;
- head->next = temp;
- temp->back = head;
- temp->next->back = temp;
- }
- //删除链表的(非尾结点的)最后一个结点
- void deleteNode()
- {
- node *temp = tail->back;
- node *bTemp = temp->back;
- bTemp->next = tail;
- tail->back = bTemp;
- temp->next = temp->back = NULL;
- free(temp);
- temp = NULL;
- }
- //删除整个链表
- void deleteLink()
- {
- while(head->next != tail)
- deleteNode();
- head->next = tail->back = NULL;
- free(head);
- free(tail);
- }
复制代码 windows下(最好用trubo c VC行也行麻烦点貌似要装easyx 应为有graphics.h)- #define N 200
- #include <graphics.h>
- #include <stdlib.h>
- #include <dos.h>
- #define LEFT 0x4b00
- #define RIGHT 0x4d00
- #define DOWN 0x5000
- #define UP 0x4800
- #define ESC 0x011b
- int i,key;
- int score=0;/*得分*/
- int gamespeed=50000;/*游戏速度自己调整*/
- struct Food
- {
- int x;/*食物的横坐标*/
- int y;/*食物的纵坐标*/
- int yes;/*判断是否要出现食物的变量*/
- }food;/*食物的结构体*/
- struct Snake
- {
- int x[N];
- int y[N];
- int node;/*蛇的节数*/
- int direction;/*蛇移动方向*/
- int life;/* 蛇的生命,0活着,1死亡*/
- }snake;
- void Init(void);/*图形驱动*/
- void Close(void);/*图形结束*/
- void DrawK(void);/*开始画面*/
- void GameOver(void);/*结束游戏*/
- void GamePlay(void);/*玩游戏具体过程*/
- void PrScore(void);/*输出成绩*/
- /*主函数*/
- void main(void)
- {
- Init();/*图形驱动*/
- DrawK();/*开始画面*/
- GamePlay();/*玩游戏具体过程*/
- Close();/*图形结束*/
- }
- /*图形驱动*/
- void Init(void)
- {
- int gd=DETECT,gm;
- initgraph(&gd,&gm,"c:\\tc");
- cleardevice();
- }
- /*开始画面,左上角坐标为(50,40),右下角坐标为(610,460)的围墙*/
- void DrawK(void)
- {
- /*setbkcolor(LIGHTGREEN);*/
- setcolor(11);
- setlinestyle(SOLID_LINE,0,THICK_WIDTH);/*设置线型*/
- for(i=50;i<=600;i+=10)/*画围墙*/
- {
- rectangle(i,40,i+10,49); /*上边*/
- rectangle(i,451,i+10,460);/*下边*/
- }
- for(i=40;i<=450;i+=10)
- {
- rectangle(50,i,59,i+10); /*左边*/
- rectangle(601,i,610,i+10);/*右边*/
- }
- }
- /*玩游戏具体过程*/
- void GamePlay(void)
- {
- randomize();/*随机数发生器*/
- food.yes=1;/*1表示需要出现新食物,0表示已经存在食物*/
- snake.life=0;/*活着*/
- snake.direction=1;/*方向往右*/
- snake.x[0]=100;snake.y[0]=100;/*蛇头*/
- snake.x[1]=110;snake.y[1]=100;
- snake.node=2;/*节数*/
- PrScore();/*输出得分*/
- while(1)/*可以重复玩游戏,压ESC键结束*/
- {
- while(!kbhit())/*在没有按键的情况下,蛇自己移动身体*/
- {
- if(food.yes==1)/*需要出现新食物*/
- {
- food.x=rand()()%400+60;
- food.y=rand()()%350+60;
- while(food.x%10!=0)/*食物随机出现后必须让食物能够在整格内,这样才可以让蛇吃到*/
- food.x++;
- while(food.y%10!=0)
- food.y++;
- food.yes=0;/*画面上有食物了*/
- }
- if(food.yes==0)/*画面上有食物了就要显示*/
- {
- setcolor(GREEN);
- rectangle(food.x,food.y,food.x+10,food.y-10);
- }
- for(i=snake.node-1;i>0;i--)/*蛇的每个环节往前移动,也就是贪吃蛇的关键算法*/
- {
- snake.x[i]=snake.x[i-1];
- snake.y[i]=snake.y[i-1];
- }
- /*1,2,3,4表示右,左,上,下四个方向,通过这个判断来移动蛇头*/
- switch(snake.direction)
- {
- case 1:snake.x[0]+=10;break;
- case 2: snake.x[0]-=10;break;
- case 3: snake.y[0]-=10;break;
- case 4: snake.y[0]+=10;break;
- }
- for(i=3;i<snake.node;i++)/*从蛇的第四节开始判断是否撞到自己了,因为蛇头为两节,第三节不可能拐过来*/
- {
- if(snake.x[i]==snake.x[0]&&snake.y[i]==snake.y[0])
- {
- GameOver();/*显示失败*/
- snake.life=1;
- break;
- }
- }
- if(snake.x[0]<55||snake.x[0]>595||snake.y[0]<55||
- snake.y[0]>455)/*蛇是否撞到墙壁*/
- {
- GameOver();/*本次游戏结束*/
- snake.life=1; /*蛇死*/
- }
- if(snake.life==1)/*以上两种判断以后,如果蛇死就跳出内循环,重新开始*/
- break;
- if(snake.x[0]==food.x&&snake.y[0]==food.y)/*吃到食物以后*/
- {
- setcolor(0);/*把画面上的食物东西去掉*/
- rectangle(food.x,food.y,food.x+10,food.y-10);
- snake.x[snake.node]=-20;snake.y[snake.node]=-20;
- /*新的一节先放在看不见的位置,下次循环就取前一节的位置*/
- snake.node++;/*蛇的身体长一节*/
- food.yes=1;/*画面上需要出现新的食物*/
- score+=10;
- PrScore();/*输出新得分*/
- }
- setcolor(4);/*画出蛇*/
- for(i=0;i<snake.node;i++)
- rectangle(snake.x[i],snake.y[i],snake.x[i]+10,
- snake.y[i]-10);
- delay(gamespeed);
- setcolor(0);/*用黑色去除蛇的的最后一节*/
- rectangle(snake.x[snake.node-1],snake.y[snake.node-1],
- snake.x[snake.node-1]+10,snake.y[snake.node-1]-10);
- } /*endwhile(!kbhit)*/
- if(snake.life==1)/*如果蛇死就跳出循环*/
- break;
- key=bioskey(0);/*接收按键*/
- if(key==ESC)/*按ESC键退出*/
- break;
- else
- if(key==UP&&snake.direction!=4)
- /*判断是否往相反的方向移动*/
- snake.direction=3;
- else
- if(key==RIGHT&&snake.direction!=2)
- snake.direction=1;
- else
- if(key==LEFT&&snake.direction!=1)
- snake.direction=2;
- else
- if(key==DOWN&&snake.direction!=3)
- snake.direction=4;
- }/*endwhile(1)*/
- }
- /*游戏结束*/
- void GameOver(void)
- {
- cleardevice();
- PrScore();
- setcolor(RED);
- settextstyle(0,0,4);
- outtextxy(200,200,"GAME OVER");
- getch()();
- }
- /*输出成绩*/
- void PrScore(void)
- {
- char str[10];
- setfillstyle(SOLID_FILL,YELLOW);
- bar(50,15,220,35);
- setcolor(6);
- settextstyle(0,0,2);
- sprintf(str,"score:%d",score);
- outtextxy(55,20,str);
- }
- /*图形结束*/
- void Close(void)
- {
- getch()();
- closegraph();
- }
复制代码 |
|