Linux下基于SDL图形库的贪吃蛇游戏_第1页
Linux下基于SDL图形库的贪吃蛇游戏_第2页
Linux下基于SDL图形库的贪吃蛇游戏_第3页
Linux下基于SDL图形库的贪吃蛇游戏_第4页
Linux下基于SDL图形库的贪吃蛇游戏_第5页
已阅读5页,还剩12页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、浙江大学硕士学位论文 序言中文论文题目:在LINUX平台下实现贪吃蛇 英文论文题目:Game of Snake under Linux 姓名及手机号: 学 号: 指 导 教 师 : 1浙江大学硕士学位论文 11个人简历在LINUX平台下实现贪吃蛇摘要: 本文主要展示了在LINUX平台下实现贪吃蛇。主要应用了双向链表、二维结构数组等数据结构,采用了SDL图形库。建模、设计算法完毕之后,在Linux下进行了运行和调试。关键词: 贪吃蛇 链表 苹果 SDLGame of Snake under LinuxAbstract: This paper mainly shows the game of sn

2、ake under Linux.The main data structures are double linked list and two-dimensional array,and I used the SDL to print the snake and apple.After modeling and completed the codes,I run the game under Linux.Key Words:snake linked-list apple SDL1. 引言贪吃蛇是一款家喻户晓的小游戏,受到众多青少年的喜爱,在手机上,在电脑上,我们都可以方便的下载到这款小游戏。而

3、在linux系统下,一样可以利用GNU gcc编译器,使用C语言编程,调用linux自带的图形库函数来完成贪吃蛇的制作。我在制作本程序时,没有参考任何相关代码,完全独立设计。2. 建模与算法问题一、贪吃蛇的表示注意到贪吃蛇是一条蛇,而且它的身体的长度是一节一节的,每一节身体都应当存储坐标与其他数据,显然我应当使用一个链表这个数据结构来处理贪吃蛇的主要程序结构。链表结构如下图所示:head NIL data1 next prev data2 next prev data3 NIL 为了起到更好的遍历和数据读取的效果,我采取了双向链表的方式,允许让后一结点方便快捷地获取前结点的相关信息。头的pre

4、v指针和尾的next指针被设置为NIL。初始的蛇结构仅有两段身体,即头和尾。其中,这个双向链表的data数据有三个,一个是当前方块在对应可活动区域的的相对坐标x,另一个是坐标y,有了这个x和y,当此身体节点方块移动以后,我们可以根据其x和y的值画出相应的蛇结构。另外一个数据储存了prev结点在之前移动过的方向,这样,当蛇头朝某个方向前进一步时,后面的身体结点就可以根据前一结点移动过的方向来移动自己。有了这三个数据,我就可以呈现整条蛇头改变方向,后面的身体移动到prev结点的位置的动态效果了。问题二、墙体和某方块已被占据的表示这是贪吃蛇结构的又一个难点,由于双向链表仅仅表示了蛇的身体结构,仅仅通

5、过蛇的坐标表示,程序是无法获取四周的墙壁信息以及是否撞到了自己的身体这些信息的。由于整个蛇体可活动区域被分成了块状区域,蛇的着色和移动都是方块化的,那么很容易就可以分析出来整个区域类似于一个表格,可以用一个二维数组来定义每个方块是否被蛇或者墙占据。如果某个方块在二维数组上对应的值是0,那么说明当前方块为空,贪吃蛇可以移动到此方块上来;如果对应的值是1,那么说明当前方块是墙壁或者是贪吃蛇自己的身体,若蛇头移动到了这个位置则游戏失败。问题三、苹果的设置众所周知,贪吃蛇通过吃苹果来增加自己的身体长度,那么就会产生一些问题。首先是苹果如何放置,因为我们已经通过二维数组将蛇的可活动区域划分成了表格的形状

6、,因此我们可以调用随机函数,在可活动区域中随机选择一个位置来放置苹果。但是如果这样放置的话,可能会出现苹果放在了蛇的身体位置,或者放在了墙上。因此,需要进行一个循环判定,如果数组的值是1说明不可放置苹果,重新获取随机数,直到选择了可放置的位置。但是,当蛇头遇到苹果的时候,如何判定贪吃蛇吃到了呢?这个问题有多种解决方案:(1) 可以令苹果的坐标参数为全局变量,然后当蛇头移动时,在某个函数里判断蛇头的相对坐标和苹果的坐标是否相等,如果相等则可以扩张链表。(2) 可以将二维数组中的每个元素都设置多个数据,即定义一个结构,多设置一个变量,该变量默认的值为0,当有苹果放在二维数组的对应位置时,该值更改为

7、1;当苹果被贪吃蛇吃掉的时候,更改为0。(3) 不改变二维数组的数据结构,但是把二维数组里苹果对应的坐标的值更改为2,即它不是墙也不是可移动区域,而是苹果,当蛇头移动到该位置时候,若发现对应二维数组的值是2,则吃到了苹果。在本程序里,我选择了第二种方案,将二维数组定义为二维结构数组。问题四、算法设计数据结构设计完毕,我们就开始了算法的设计。本程序中,需要实现的功能有:游戏界面的设计、贪吃蛇身体结构的展现、苹果的设置、贪吃蛇的移动、移动速度的更改等。(1) 游戏界面的设计由于是在linux下完成,因此我将会用到linux的图形库函数,来完成贪吃蛇可活动区域的建立、游戏名称、分数界面和一些提示的展

8、现。首先,我选择的视频模式是640x480x16位色,然后,我在屏幕上选择了一块400x400的区域用来当做贪吃蛇的可活动区域。在这块区域的边界处,我设置了一个矩形框,用来提醒玩家这里是墙,不可碰撞。这400x400的区域被1600个小矩形所分割,每个矩形的大小为40x40,以横向为x轴,纵向为y轴,就可以看成一个40x40的二维数组,每个数组对应位置的坐标都是0。但是由于在可活动区域外还有一堵墙存在,因此二维数组需要被设置为42x42,最外围一圈的标记值为1。而在剩下的空白处,我显示了一些标题文字、按键提醒文字。整个游戏界面就初步建立了。(2) 贪吃蛇身体结构的展现在数据结构的建立中,我将贪

9、吃蛇设置为一个双向链表,而双向链表里存储的数据,就是贪吃蛇的身体在40x40的区域内,每个结点的相对坐标,范围为(0,0)到(40,40),初始的蛇只有头尾,其坐标分别为(20,20)和(19,20),只要将这两个点转化为绝对坐标,把队应的10*10的小矩形区域修改成一定的颜色,就可以画出一条蛇。当蛇的身体移动或者变长的时候,每个身体节点的对应的坐标值也相应改变,再重新打印这条蛇即可。(3) 苹果的设置前文已经提到,只需要通过rand函数,获取两个0-40的随机数的值,分别对应苹果的x坐标和y坐标,并通过一定的循环避免苹果设置在蛇的身体上或者墙上即可。(4) 贪吃蛇的移动在程序中,我用一个sn

10、ake *move()函数来实现蛇的移动,而这个功能的实现也是整个程序的核心。在双向链表数据结构中,我定义了一个重要的变量Dir来表示本方块的移动方向。比如程序从键盘中断读入RIGHT按键之后,贪吃蛇向右移动一步,那么Dir的值就会被赋为RIGHT,其中RIGHT是键盘上向右键的ACSII码值,已经过宏定义。之后,当蛇头移动一步之后,蛇身除蛇头以外的方块都会读取prev结点的Dir值,并移动到prev结点的位置。对于蛇头来说,有了这个Dir变量之后,在键盘没有输入任何按键时,它会读取自己的Dir的值并作出相应的移动,相当于不更改方向,直线前进,知道键盘输入了某个方向,它才会作出相应动作并改变D

11、ir。贪吃蛇的移动同样有许多方法。更加简便的一种是只需要将蛇的最后一个结点移动到蛇头的前一个结点,并使它成为头结点。当然,前一个方法更加直观,在算法上也更加有“蛇”的效果,因此采用了前者。还有一个贪吃蛇移动的小问题,注意到贪吃蛇是不可以向后走的,即连续两次的移动方向不可以相反,否则蛇头就会沿着自己的身体前进,直接造成“撞墙”,从而Game Over,而这是我们不愿意看到的,因此要考虑避开这种情况。而贪吃蛇移动时,移速的改变可以依靠一个全局变量dtime,蛇的每次移动都延时dtime的时间,初始化的贪吃蛇的移动速度为1500ms,则只要将dtime的初值设置为1500,在蛇每次吃到苹果时将dti

12、me的值减少10,就可以做到不断加速的效果。3. 实验程序设计代码如下:#include<stdio.h>#include<time.h>#include<stdlib.h>#include<SDL/SDL.h>#include<SDL/SDL_draw.h>#define MX(x) (x)*10+121)#define MY(y) (y)*10+41)struct mysnakeint x;int y;int Dir;struct mysnake *next;struct mysnake *last; /prev;structin

13、t flag; int point;Point4242;int esc = 0;int Hdir = SDLK_RIGHT;SDL_Surface *screen;int dtime = 180;void SetGame();void Progress();void SetApple();struct mysnake *Move(struct mysnake *head,struct mysnake *tail, int movex, int movey);void Clean(struct mysnake *head);void Snake(struct mysnake *head);int

14、 main(void)if(SDL_Init(SDL_INIT_VIDEO)<0)fprintf(stderr,"Init video failed:%sn",SDL_GetError();exit(1);screen=SDL_SetVideoMode(640,480,16,SDL_SWSURFACE);if(screen=NULL)fprintf(stderr,"Set video mode failed:%sn",SDL_GetError();exit(1);atexit(SDL_Quit);SetGame();getchar();return

15、 0;void SetGame()int i, j;for (i = 0; i<42; i+)for (j = 0; j<42; j+)Pointij.flag = 0;Pointij.point = 0;for (i = 0; i<42; i+)Point0i.flag = 1;for (i = 0; i<42; i+)Point41i.flag = 1;for (i = 0; i<42; i+)Pointi0.flag = 1;for (i = 0; i<42; i+)Pointi41.flag = 1;Draw_Rect(screen,129,49,4

16、02,402,SDL_MapRGB(screen->format,0,0,255);Draw_FillRect(screen,130,50,400,400,SDL_MapRGB(screen->format,255,255,255);SDL_WaitEvent(NULL);Progress();void Progress()struct mysnake *head, *tail; int key;SDL_Event event;head = (struct mysnake *)malloc(sizeof(struct mysnake);tail = (struct mysnake

17、*)malloc(sizeof(struct mysnake);head->next = tail;head->last=NULL;head->x = 20;head->y = 20;head->last = NULLhead->Dir=RIGHT;Point2020.flag = 1;tail->next = NULL; tail->last=head;tail->x = 19;tail->y = 20;tail->Dir=RIGHT;Point1920.flag = 1;Snake(head); SetApple();whi

18、le (!esc)SDL_Delay(dtime);while(SDL_PollEvent(&event)if(event.type=SDL_KEYDOWN)switch (event.type)case SDLK_RIGHT:if (before != SDLK_LEFT)Hdir=SDLK_RIGHT; break;case SDLK_LEFT:if (before != SDLK_RIGHT)Hdir=SDLK_LEFT; break;case SDLK_DOWN:if (before != SDLK_UP)Hdir=SDLK_DOWN; break;case SDLK_UP:i

19、f (before != SDLK_DOWN)Hdir=SDLK_UP; break;case SDLK_SPACE:SDL_WaitEvent(NULL); break;case SDLK_ESCAPE:fprintf(stdin,"Compulsory Withdrawal!n");SDL_Delay(10);esc=1;break;else if(event.type=SDL_QUIT)esc=1;switch (Hdir)case SDLK_RIGHT:head = Move(head,tail, 1, 0); break;case SDLK_LEFT:head =

20、 Move(head,tail, -1, 0); break;case SDLK_DOWN:head = Move(head,tail, 0, 1); break;case SDLK_UP:head = Move(head,tail, 0, -1); break;SDL_UpdateRect(screen, 0, 0, 0, 0);void SetApple()int PX = 0, PY = 0;srand(time(NULL);while(PointPXPY.flag) PX = rand() % 40;PY = rand() % 40; delay(10);PointPXPY.point

21、 = 1;Draw_FillRect(screen,MX(PX), MY(PY),8,8,SDL_MapRGB(screen->format,255,255,0);struct mysnake *Move(struct mysnake *head,struct mysnake *tail, int movex, int movey)struct mysnake *p;if(Pointhead->x + movexhead->y + movey.flag)fprintf(stdin,"Game Over!n");SDL_Delay(10);esc = 1;r

22、eturn head;Clean(head);if (Pointhead->x + movexhead->y + movey.point)Pointhead->x + movexhead->y + movey.point=0; Pointhead->x + movexhead->y + movey.flag=1;p = (struct mysnake *)malloc(sizeof(struct mysnake);head->last=p;p->next = head;p->x = head->x + movex;p->y =

23、head->y + movey;head = p;head->Dir=Hdir; if(dtime>=50)dtime = dtime - 5;SetApple();else if (!Pointhead->x + movexhead->y + movey.flag) head->x = head->x + movex;head->y = head->y + movey;for (p = tail; p->last!=NULL; p = p->last)p->Dir=p->last->Dir;head->

24、Dir=Hdir;for (p = head->next; p!= NULL; p = p->next)switch (p->Dir)case SDLK_RIGHT: p->x+; break;case SDLK_LEFT: p->x-; break;case SDLK_DOWN: p->y+; break;case SDLK_UP: p->y-; break;Snake(head);return head;void Clean(struct mysnake *head)struct mysnake *p;for (p = head; p != NULL; p = p->next)Pointp->xp->y.flag=0;Draw_FillRect(screen,MX(p->x), MY(p->y),

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论