贪吃蛇c程序设计报告含c代码.docx

上传人:b****9 文档编号:25522436 上传时间:2023-06-09 格式:DOCX 页数:31 大小:157.11KB
下载 相关 举报
贪吃蛇c程序设计报告含c代码.docx_第1页
第1页 / 共31页
贪吃蛇c程序设计报告含c代码.docx_第2页
第2页 / 共31页
贪吃蛇c程序设计报告含c代码.docx_第3页
第3页 / 共31页
贪吃蛇c程序设计报告含c代码.docx_第4页
第4页 / 共31页
贪吃蛇c程序设计报告含c代码.docx_第5页
第5页 / 共31页
点击查看更多>>
下载资源
资源描述

贪吃蛇c程序设计报告含c代码.docx

《贪吃蛇c程序设计报告含c代码.docx》由会员分享,可在线阅读,更多相关《贪吃蛇c程序设计报告含c代码.docx(31页珍藏版)》请在冰豆网上搜索。

贪吃蛇c程序设计报告含c代码.docx

贪吃蛇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

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 信息与通信

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1