贪吃蛇c程序设计报告含c代码.docx
- 文档编号:25522436
- 上传时间:2023-06-09
- 格式:DOCX
- 页数:31
- 大小:157.11KB
贪吃蛇c程序设计报告含c代码.docx
《贪吃蛇c程序设计报告含c代码.docx》由会员分享,可在线阅读,更多相关《贪吃蛇c程序设计报告含c代码.docx(31页珍藏版)》请在冰豆网上搜索。
贪吃蛇c程序设计报告含c代码
贪吃蛇
一实验目的
1、了解AVRATmega128试验箱的基本构成
2、熟悉键盘的工作原理和设置
3、熟悉点阵的工作原理和设置
4、熟悉液晶显示器的工作原理和设置
5、熟悉语音播放的工作原理和设置
6、熟悉AVRATmega128的中断功能
7、初步掌握用C语言编程的能力
二实验内容:
1、设计题目:
根据液晶显示器中的提示,通过对4*4键盘的按键输入,选择游戏的难度,继而控制点阵中点列的移动、长度的增加,只有在规定的时间(30秒、20秒、10秒)内完成任务(吃10个),就可游戏胜利,否则失败。
同时在游戏的开始、胜利、失败时都将伴随着声音的输出。
三硬件原理
1、AVRATmega128单片机及片外选址电路
2、LDM点阵显示电路
3、LCD液晶显示电路
4、键盘连接电路及语音输出连接电路
四程序流程图
(1)、主函数
只有在规定的时间内完成“吃下”10个点,游戏才能成功,除了上图中的当第一点碰触到自身点导致失败情况下,在规定的时间内没有完成任务,将会导致中断相应,推出程序运行,最终游戏失败。
(2)、随机点产生函数void_rand(void)
函数中应用了产生随机点的函数rand(),其头文件必须包括“#include
(3)、第一点的操作函数voidoperate(unsignedcharin)
产生第一点运动后的在点阵中显示的码值(数组change[])
Leader_i,leader_j分别为第一点相对于点阵中左上角上的点的绝对坐标值,其中每一个点的直径长设为1。
(4)、擦除函数void_eraser(void)
产生被擦除点的码值的反(eraser[])
由于最后一个点的位置可以由第一个点根据先前操作逆走N步得到,所以eraser_i=leader_i+n1-n2和eraser_j=leader_j+n3-n4得到被擦除点相对于点阵左上点的绝对坐标。
由于eraser_i、eraser_j可能为负值,因而为求得最后一个点在点阵中的位置,使其任意加一足够大的能被8整除的正整数(设为800),再与8除求余。
即:
eraser_i=(eraser_i+800)%8,eraser_j=(eraser_j+800)%8。
后经eraser[eraser_i]=~(1< (5)、状态保存函数voidstatus_save(void) 将前一状态与第一点移动后产生的第一点新码值(change[])进行或运算,再与产生的被擦除点显示码值的反(eraser[])进行与运算,得到新的显示状态(除随机点)的码值。 (6)、第一点的操作过程记录函数voidrenew(unsignedcharin) 根据需要记录第一个点的N个运行过程(设为20) (7)、吃点函数voideat(unsignedcharin) 将记录的随机点显示码值的数组font[]清零,让第一个点再向前操作一步,但不擦除最后一个点,用来实现吃点效果。 最后调用产生随机点函数重新产生一随机点。 (8)、结合函数voidjoin(void) 用于产生要显示的码值。 将表示状态的数组status[]与表示随机点的数组font[]进行或运算就可以实现。 (9)、测试函数unsignedchartest(unsignedchar*tester) 这个函数在程序中用于两个地方,一是在产生随机点的函数中,如果产生的随机点在“蛇”身上(返回值为2),则重新产生随机点;二是在第一个操作完一步后,判断此时第一点的位置,如果在“蛇”身上(返回值为2),则游戏失败。 (10)、液晶显示器显示函数voidprint_message(char*message) 用于显示字符串message。 (11)、函数voidstart(void)、void_win(void)、voidlose(void)用于在游戏开始时、胜利时、失败时的液晶显示、语音输出以及LED点阵输出。 (12)、难度选择函数voidchoose(void) 根据液晶显示的提示,选择游戏难度等级。 在按确认键后开中断。 程序流程图如下: (13)、中断程序SIGNAL(SIG_OVERFLOW3) 用于限制游戏进行的时间,在规定时间内完成游戏任务,则关中断,中断程序不在执行,如果在规定时间没有完成,则调用失败函数(lose()),游戏失败。 程序流程图如下: 5.c程序代码: /**************************************************** DOS游戏,贪吃蛇。 编辑器Win-TC,编译器TC2内核。 作者: 樊毅。 时间: 年10月10日。 注意: 贪吃蛇的数据结构要用双向链表实现,因为蛇没有吃到食物时,是在蛇头前加一个节点作为新的蛇头,把蛇尾删去,实现移动一格,同时,蛇长不变。 从尾部删除链表的一个节点就必须用双向链表了。 ****************************************************/ #include #include #include #include #include #include #include #include /*定义地图小格的边长*/ #defineSIZE10 #defineUP0x4800 #defineDOWN0x5000 #defineLEFT0x4B00 #defineRIGHT0x4D00 #defineENTER0x1C0D voidfill(intx,inty,intxx,intyy,intcolor); voidinitg(); voidwin_title(); intwin_menu(); voidblock(intx,inty,intcolor); voiddraw_map(); voidinit_snake(); voidprints(); voidfree_snake(); voidsnake_move(); voidinit_map(); voidfood(); voidgame(); voidprint_scores(); voidpr_warn(intx,inty); voidhelp(); enum{d_up,d_down,d_left,d_right}DIR=d_left;/*定义一个全局的方向类型的枚举变量DIR,初始方向为左。 其值前面加"d_"和全局变量的键值区分。 */ structsnake/*定义蛇体的每个小方块的数据结构。 */ { charx;/*每个蛇体方块结构的x,y记录蛇体方块的方块坐标。 方块坐标就是以一个方块为单位的坐标。 */ chary; structsnake*pre;/*蛇体前指针,指向前一个蛇体方块结构的开始*/ structsnake*next;/*蛇体后指针,指向后一个蛇体方块结构的开始*/ }*HEAD=NULL,*TAIL=NULL;/*定义两个全局的结构体指针用于保存蛇头和蛇尾的位置*/ charOVER[]="GameOver! ";/*用于游戏失败输出的字符串。 */ charWIN[]="YouWin! ";/*用于游戏胜利输出的字符串。 */ charMAP[40][60];/*定义一个全局变量数组,用于标记地图方格属性.空地,蛇身,食物.*/ intGAME=0;/*定义一个全局变量GAME对游戏状态进行记录。 不结束游戏.1,结束游戏.*/ intLENGTH=3;/*定义一个全局变量LENGTH记录蛇体长度。 初始长度为.*/ intDIFF=0;/*定义游戏难度全局变量。 */ intDELAY=20;/*定义延时时间全局变量。 单位是百分之一秒,即,0.01秒.初始值,表示延时.2秒。 */ intS_SIZE=sizeof(structsnake);/*定义一个全局变量用来存放structsnake结构所占字节数,方便使用。 */ /***************************************** 下面是,填充一定范围的函数,x,y是填充范围的左上角坐标,xx,yy是右下角坐标。 color是填充颜色。 bar()函数中,x,y 加,xx,yy减,是因为边框线有宽度,所以,要把填充范围往内缩一点。 *****************************************/ voidfill(intx,inty,intxx,intyy,intcolor)/*以(x+1,y+1)为左上角,以(xx-1,yy-1)为右下角,用指定颜色填充此范围。 */ { setfillstyle(SOLID_FILL,color);/*SOLID_FILL表示以单一的实体颜色填充,color是填充颜色。 */ bar(x+1,y+1,xx-1,yy-1);/*以(x+1,y+1)为左上角,以(xx-1,yy-1)为右下角画条形。 */ } voidinitg()/*把显示器初始化成图像模式,屏幕的大小为640*480像素。 函数中还有错误检查程序。 */ { intgdriver,gmode,errorcode; gdriver=VGA;/*图形驱动器*/ gmode=VGAHI;/*图形模式*/ registerbgidriver(EGAVGA_driver);/*该函数告诉连接程序在连接时把EGAVGA的驱动程序装入到用户的执行程序中*/ initgraph(&gdriver,&gmode,"");/*初始化图形系统*/ errorcode=graphresult();/*返回最后一次不成功的图形操作的错误代码,没有错误返回*/ if(errorcode! =0) { printf("\n\terror: \t%s\n",grapherrormsg(errorcode));/*grapherrormsg返回一个错误信息串的指针*/ getch();/*从控制台无回显地取一个字符,不需要回车。 就是为了等待用户按键以后,退出整个程序。 */ exit (1); } } voidwin_title()/*绘制游戏主菜单页面的标题字符串。 */ { charstr1[]="DOSGameSnake"; charstr2[]="byFineFan"; setviewport(200,55,440,140,1);/*以(200,55)为左上角,(440,140)为右下角设置一个视口。 */ settextjustify(0,2);/*设置字符串横向左对齐,纵向顶部对齐。 */ settextstyle(0,0,2);/*设置字符串字体为第一个对应的字体,第二个表示水平输出,字体大小为。 */ setcolor(WHITE); outtextxy(10,10,str1); outtextxy(20,50,str2); } voiddraw_menu(inti)/*根据i的取值,画出不同状态的菜单。 */ { intmidx,midy; charstart[]="Start"; charexit[]="Exit"; charhelp[]="Help"; midx=getmaxx()/2;/*midx表示窗口的中心的X坐标,getmaxx()函数返回当前图像窗口的X坐标的最大值,下一行类似。 */ midy=getmaxy()/2; setviewport(midx-40,midy-30,midx+40,midy+60,0); settextjustify(0,2);/*设置字符串横向左对齐,纵向顶部对齐。 */ settextstyle(0,0,2);/*设置字符串字体为第一个对应的字体,第二个表示水平输出,字体大小为。 */ switch(i) { case0: clearviewport(); fill(0,0,80,30,YELLOW);/*i为时,把第一个选项"Start"高亮。 */ setcolor(GREEN);/*将当前图形屏幕的当前画笔颜色置为绿色,“GREEN”必须全部大写。 */ outtextxy(3,10,start); outtextxy(10,40,help); outtextxy(10,70,exit); break; case1: clearviewport(); fill(0,30,80,60,YELLOW); setcolor(GREEN); outtextxy(3,10,start); outtextxy(10,40,help); outtextxy(10,70,exit); break; case2: clearviewport(); fill(0,60,80,90,YELLOW); setcolor(GREEN); outtextxy(3,10,start); outtextxy(10,40,help); outtextxy(10,70,exit); break; } } intwin_menu()/*制作主菜单窗口,玩家选择"Start"返回,选择"Exit"返回。 */ { intkey,i=0;/*key记录键盘返回值,i根据按键变化,必须初始化为,因为后面的draw_menu()函数先要根据i值绘出菜单的初始画面。 退出后win_menu()函数返回i的值。 */ do { draw_menu(i); key=bioskey(0);/*bioskey(0)函数会使整个程序在此处暂停,直到用户按下键盘的任何一个键。 */ if(key==UP) { if(i==0)continue;/*i等于时,已经是最小值了,不能再减小了,所以结束此次循环。 */ i--; } if(key==DOWN) { if(i==2)continue;/*i等于时,已经是最大值了,不能再增大了,所以结束此次循环。 */ i++; } if(key==ENTER)break; } while (1); returni; } voidblock(intx,inty,intcolor)/*填充小方块的函数.x,y是小方块的方块坐标。 */ { fill(x*SIZE,y*SIZE,x*SIZE+SIZE,y*SIZE+SIZE,color);/*此处本来应该将前一对坐标分别加,后一对坐标分别减,才能把小 方块之间的分隔线留出来,但是,fill()函数中已经做了这一步,所以此处不用做了。 用此函数画 蛇体的小方块时也一样,坐标不用再变化了,因为fill()函数已经把空隙留出来了。 */ } voidhelp()/*输出按键说明画面。 */ { charh1[]="KeyUptoturnup."; charh2[]="KeyDowntoturndown."; charh3[]="KeyLefttoturnleft."; charh4[]="KeyRighttoturnright."; charh5[]="KeyEntertoenterorreturn."; setviewport(0,0,639,479,0);/*建立一个全屏视口,因为坐标从开始,所以,虽然横向有个像素,但,横坐标最大值是,纵坐标同理,横纵坐标一定不能超过最大值 639和479,否则,会出错,例如,建立的视口不是全屏,而是,只占据部分屏幕的视口。 */ fill(0,0,639,479,LIGHTGRAY); setcolor(RED); setlinestyle(0,0,3); rectangle(3,3,636,476); settextjustify(0,2);/*设置字符串横向左对齐,纵向顶部对齐。 */ settextstyle(0,0,2);/*设置字符串字体为第一个对应的字体,第二个表示水平输出,字体大小为。 */ setcolor(BLUE); outtextxy(30,30,h1); outtextxy(30,70,h2); outtextxy(30,110,h3); outtextxy(30,150,h4); outtextxy(30,190,h5); while (1)/*等待玩家按Enter键,返回主菜单。 */ { if(bioskey (1)) { if(bioskey(0)==ENTER)return; } } } voiddraw_map()/*绘制游戏的地图。 */ { charmap_title[]="GameSnakeScores: "; inti=0,j=0; cleardevice();/*清除全屏的显示内容。 */ setviewport(20,40,620,80,0);/*建立地图标题栏的视口。 屏幕中心像素坐标为(320,240),由此可以算出setviewport()函数的前四个坐标参数的值。 */ fill(0,0,600,40,YELLOW);/*将地图标题栏填充底色为黄色.*/ setcolor(WHITE); rectangle(-3,-3,603,40); settextjustify(0,2);/*设置字符串横向左对齐,纵向顶部对齐。 */ settextstyle(0,0,2);/*设置字符串字体为第一个对应的字体,第二个表示水平输出,字体大小为。 */ setcolor(LIGHTBLUE);/*设置地图标题文字的颜色。 */ outtextxy(10,10,map_title); setviewport(20,80,620,440,0);/*建立地图的方块部分的视口,大小为,600*360.可以划分成60*36个小方块.地图的方块部分应该重新建立视口,方便以后进行蛇体是否 出界的判断条件的设定,方便以后放置食物时,食物坐标的设定。 */ setcolor(WHITE); rectangle(-3,0,603,363);/*画地图边框线,*/ for(i=0;i<600;i+=SIZE) for(j=0;j<360;j+=SIZE) { fill(i,j,i+10,j+10,LIGHTGRAY); } } voidinit_snake()/*初始化蛇体,产生游戏刚开始时的三个蛇体方块的数据。 因为,有时要从尾部删除蛇尾节点,所以必须用双向链表。 */ {/*最初的三个蛇体方块的方块坐标分别为(40,10)(41,10)(42,10)。 */ structsnake*p; HEAD=p=(structsnake*)malloc(S_SIZE); p->x=40; p->y=10; p->pre=NULL; MAP[10][40]=1;/*二维数组对应一块平面区域时,行坐标是纵坐标y,列坐标是横坐标x。 */ p->next=(structsnake*)malloc(S_SIZE); p->next->pre=p; p=p->next; p->x=41; p->y=10; MAP[10][41]=1; p->next=(structsnake*)malloc(S_SIZE); p->next->pre=p; p=p->next; p->x=42; p->y=10; MAP[10][42]=1; p->next=NULL; TAIL=p; } voidprints()/*显示蛇体的函数。 */ { structsnake*p; if(HEAD==NULL)return;/*对蛇体为空的情况不予显示,否则,会显示错误,例如,在地图画面的左上角显示一个绿色小方块.*/ block(HEAD->x,HEAD->y,LIGHTBLUE);/*先把蛇头画出,画成淡蓝色。 */ for(p=HEAD->next;p! =NULL;p=p->next) { block(p->x,p->y,LIGHTGREEN); } } voidfree_snake()/*释放蛇体所占的内存。 */ { structsnake*p1,*p2; p1=HEAD; HEAD=NULL; for(;p1! =NULL;) { p2=p1; p1=p1->next; free(p2); } } voidpr_warn(intx,inty)/*形参x,y表示输出警告字符串的像素坐标。 此处的坐标是在地图方块部分内的相对像素坐标。 */ { charwarn1[]="Playgames,don'tbeplayedbygames! "; charwarn2[]="Studynow! ! ! ! Worknow! ! ! ! "; fill(x-10,y-10,x+590,y+60,YELLOW); settextjustify(0,2);/*设置字符串横向左对齐,纵向顶部对齐。 */ settextstyle(0,0,2);/*设置字符串字体为第一个对应的字体,第二个表示水平输出,字体大小为。 */ setcolor(RED); outtextxy(x,y,warn1); outtextxy(x,y+40,warn2); } voidsnake_move()/*蛇体移动函数,此函数内,完成了对蛇体是否撞墙,是否撞到自己,是否吃到食物的检测,并做相应操作.*/ { structsnake*p; p=HEAD; HEAD=(structsnake*)malloc(S_SIZE);/*建立蛇体移动到下一步的蛇头HEAD,并暂时把当前蛇头的方块坐标赋值给下一步的蛇头。 */ HEAD->x=p->x;/*此时,下一步的蛇头还没有和蛇体连接上。 */ HEAD->y=p->y; switch(DIR)/*根据方向,改变下一步的蛇头的方块坐标.*/ { cased_up: HEAD->y--; break; cased_down: HEAD->y++; break; cased_left: HEAD->x--; break; cased_right: HEAD->x++; break; } if(H
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 贪吃 程序设计 报告 代码