贪吃蛇程序设计报告(附C源码)
目 录
1. 课程设计内容 ............................................................................................. 2 2. 课程设计目的 ............................................................................................. 2 3. 背景知识(可选项) .................................................................................. 2 4. 工具/准备工作(可选项) .......................................................................... 3 5. 设计步骤、方法等 . ..................................................................................... 3
5.1. 步骤1:步骤名称(二级标题) ......................................................................................... 3
步骤1.1:步骤名称(三级标题) ............................................ 错误!未定义书签。 5.1.1.
5.2.
5.3. 步骤2:步骤名称 . ........................................................................................................... 5 步骤n :步骤名称 . ........................................................................................................... 7 6. 设计结果及分析 ......................................................................................... 9 7. 设计结论 .................................................................................................... 9 8. 问题及心得体会 ......................................................................................... 9 9. 对本设计过程及方法、手段的改进建议 . ................................................... 10 10. 参考文献 .................................................................................................. 11
报告名称
1. 课程设计内容
产生一个固定大小没有边界的游戏区域,蛇从区域的中心开始,由玩家通过键盘控制蛇的运动方向,用蛇头去吃随机分布在游戏区域内的食物;
蛇的运动限制在游戏区域内,游戏区域没有边界,所以蛇在区域内作循环运动;
蛇的运动方向为直线运动,只走横和竖的方向,不走斜线;
蛇的运动速度由游戏的难度来控制,难度越高,速度越快,游戏难度分为9个等级;
蛇身体的长度从1开始每吃掉一份食物就增加一个长度;
食物的出现安照随机分布的原则,蛇吃掉一份后随即在游戏区域内放一份新的食物;
每吃掉一份食物得分为10*游戏的难度,游戏结束后统计全部的得分; 游戏结束的条件为:在控制蛇的过程中蛇头碰到蛇的身体的任何部位;
2. 课程设计目的
(1)、通过c 语言编程实现贪吃蛇游戏的运行。
(2)、对代码进行进一步的调试优化,以使游戏高效运行,操作化强,人性
化强。
(3)、通过编程,使自己掌握C 语言编程的基本方法,有独立编程的能力,
并学到实战经验。
3. 背景知识(可选项)
本程序主要是一个交互式的游戏程序,通过玩家的键盘上下左右键控制贪
吃蛇的运动方向。
程序会根据您按下的键判断贪吃蛇走向。
运行环境
本程序运行时需要硬件环境和支持环境。
a. 硬件环境:一般的PC 机
b. 软件环境:WINGDOWS 95或以上
这个程序的关键是表示蛇的图形以及蛇的移动。用一个小矩形表示蛇的一节身体,身体每长一节,增加一个矩形块。移动时必须从蛇头开始,所以蛇不能向相反方向移动,也就是蛇尾不能改作蛇头。如果不按任何键,蛇自行在当前方向上前移,当游戏者按了有效的方向键后,蛇头朝着指定的方向移动,一步移动一节身体,所以当按了有效的方向键后,先确定蛇头的位置,然后蛇身体随着蛇头移动,图形的实现是从蛇头的新位置开始画出蛇,这时由于没有清屏的原因,原来蛇的位置和新蛇的位置差一个单位,所以看起来社会多一节身体,所以将蛇的最后一节用背景色覆盖。食物的出现和消失也是画圆形和覆盖圆形
4. 工具/准备工作(可选项)
设计者应该首先考虑实现一个可以游动的蛇。通过寻找规律,对实际对象进行抽象概括建立对象模型,首先从物理的角度来分析蛇得运动规律。它是蠕动的,像水一样流动。他有个特性就是身体的每一个点都经过他头部所在的点,他每一个时刻骨节所要运动的目的地是他前一个骨节所在的位置。所以我们事先必须了解并掌握一些基本的画图函数,并学会调用和运行。
5. 程序设计步骤、方法。
5.1. 步骤1:图形的转换及实现
由图A 到图B 可以看到实际对象的模型到抽象模型,
图A 实际的的蛇的照片
经过抽象化
图B 蛇抽象成为骨骼状态(头和骨节)
程序设想了一个骨骼结构图
其中蛇的全身都是一样的绿边的正方形构成但是在分析时注意到
头部与其它的骨节不同,只有蛇头才能控制整个蛇的运动方向。
5.2. 步骤2:主要算法和关键数据结构
系统流程
a. 用流程图示出程序的主要控制流程和处理流程;
5.3. 步骤3:系统数据结构设计
1. struct Food /*食物的结构体*/
{
int x; /*食物的横坐标*/
int y; /*食物的纵坐标*/
int yes; /*食物是否出现的变量*/
}food;
struct Snack /*蛇的结构体*/
{
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 PrScore(void); /*分数输出函数*/
2. DELAY(char ch)/*调节游戏速度*/
{
if(ch=='3')
{
delay(gamespeed); /*delay是延迟函数*/ delay(gamespeed);
}
3. for(i=snake.node-1;i>0;i--) /*贪吃蛇的移动算法*/
{
snake.x[i]=snake.x[i-1];
snake.y[i]=snake.y[i-1]; /*贪吃蛇的身体移动算法*/
}
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;
}
6. 设计结果及分析
开始时,一直就是失败,设计了几十遍,仍然无法运行,后来经过一系列的调试查错,程序达到基本可运行,再后来经过进一步的调试,优化,算法简洁高效了很多,使得游戏达到老师的所有要求,并有很强的运行效果,可操作性,人性化强。通过和同学的一些交流,也实现一些特殊功能,使游戏更加丰富多彩。
7. 设计结论
通过此次贪吃蛇游戏的设计,确实学到了很多实战的经验。以前只是纸上谈兵,真正下起手来才发现自己其实对C 语言还没有掌握到编程的程度。开始编译之后,自己通过与同学交流,查阅资料,独立的编写出了游戏代码,并进一步优化,加强可操作性,从中得到了很多课上没有的知识,体会到了编程的快乐,也许,编程就是,由简单到复杂,由复杂到简单。
8. 问题及心得体会
刚开始时,一直失败,好多错误,其实就是些基本的错误,比如变量的定义,整型变量的范围,结构体的运用,指针的定义,函数的调用等等,通过这些问题才发现自己学习的知识是那么不牢固。再有就是些技术上的难题,比如画图函数,初次接触,需要去查阅运用。最后就是软件的问题,
比如这一节:
void Init(void)
{
int gd=DETECT,gm;
initgraph(&gd,&gm,"c:\\BGI");
cleardevice();
}
用红色字体标示的一句代码会因为路径的不同而在不同的pc 上运行效果不同,为了是代码质量高,可以改变一下软件的路径,即改变BGI 的存放路径,可以解决问题。通过一路的解决问题,也发现了自己到底哪方面存在问题,是自己的编程能力有了很大提高。
9. 对本设计过程及方法、手段的改进建议
比如一些画图函数的实现,最好选用常见普及的函数,不然在不同pc 上运行效果不同,还有一些函数效果不理想。比如控制蛇的速度的函数就有些僵化,不是太灵活,控制颜色的函数也有些单调,还有事物的出现是随机函数控制的,但随即函数存在漏洞,可能出现食物刚好出现在蛇身上的错误,对于以上的函数问题,可以通过对函数的改进及优化解决问题。
10. 参考文献
a. 贪食蛇算法C 语言版(借鉴其算法)
网址:;
b. 《Visual C++面向对象与可视化程序设计》(第二版) 编著者:黄维通 出版者:清华大学出版社 版次:2007年8月
附录:贪吃蛇游戏源代码
#define N 200
#include
#include
#include
#define LEFT 0x4b00
#define RIGHT 0x4d00
#define DOWN 0x5000
#define UP 0x4800
#define ESC 0x011b
int i,key;
int score=0;
int gamespeed=50000;
int level;
struct Food
{
int x;
int y;
int yes;
}food;
struct Snake
{
int x[N];
int y[N];
int node;
int direction;
int life;
}snake;
void Init(void);
void Close(void);
void DrawK(void);
void GameOver(void);
void GamePlay(void);
void PrScore(void);
void main(void)
{printf("welcome to play the game !\n"); printf("please input the level(1~~9): "); scanf ("%d",&level);
Init();
DrawK();
GamePlay();
Close();
}
void Init(void)
{
int gd=DETECT,gm;
initgraph(&gd,&gm,"c:\\BGI");
cleardevice();
}
void DrawK(void)
{
setcolor(11);
setlinestyle(SOLID_LINE,0,THICK_WIDTH); for(i=50;i
{
rectangle(i,40,i+10,49);
rectangle(i,451,i+10,460);
}
for(i=40;i
{
rectangle(50,i,59,i+10);
rectangle(601,i,610,i+10);
}
void GamePlay(void)
{
randomize();
food.yes=1;
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)
{
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];
}
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
{
if(snake.x[i]==snake.x[0]&&snake.y[i]==snake.y[0]) {
GameOver();
snake.life=1;
break;
}
}
if(snake.x[0]595||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
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);
}
if(snake.life==1)
break;
key=bioskey(0);
if(key==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;
}
}
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();
}