贪吃蛇游戏.docx
《贪吃蛇游戏.docx》由会员分享,可在线阅读,更多相关《贪吃蛇游戏.docx(17页珍藏版)》请在冰豆网上搜索。
贪吃蛇游戏
贪吃蛇游戏
1.实验目的………………………………………………………………
2.实验任务与要求………………………………………………………
2.1实验内容………………………………………………………………
2.2实验要求………………………………………………………………
2.3实验环境………………………………………………………………
3.设计方案…………………………………………………………………
3.1程序功能………………………………………………………………
3.2设计思想………………………………………………………………
3.3设计总体流程图………………………………………………………
3.4设计的具体实现………………………………………………………
4.程序测试…………………………………………………………………
4.1测试内容与结果………………………………………………………
5.实验总结………………………………………………………………
1.实验目的:
●复习、巩固VC6.0的基础知识,进一步加深对VC6.0技术的理解和掌握;
●课程设计为学生提供了一个既动手又动脑,独立实践的机会,将课本上的理论知识和实际有机的结合起来,锻炼学生的分析解决实际问题的能力。
●培养学生在项目开发中团队合作精神、创新意识及能力
2.实验任务与要求
2.1实验内容
贪吃蛇游戏开发,首先它可以为大家提供一种当前比较流行的休闲小游戏。
贪吃蛇是家喻户晓的益智类小游戏,选择这个题目一是为了将自己的所学知识加以运用,二是一直以来贪吃蛇这个游戏就深深地吸引着很多人,它的制作方法对于很多同学而言都是很神秘的。
所以我们希望通过这学期所学知识把它剖析开来,真真正正的了解它的本质和精髓。
在这次学习中我们将从实践和实际的项目中提高自己的编程能力。
因此决定选择这个题目作为VC#.NET的课程设计。
2.2实验要求
●对系统进行功能模块分析、控制模块分析正确,符合课题要求,实现相应功能;可以加以其他功能或修饰,使程序更加完善、合理;
●系统设计要实用,采用模块化程序设计方法,编程简练、可用,功能全面;
●说明书、流程图要清楚;
●记录设计情况(备查,也为编写设计说明书作好准备);
2.3实验环境
WindowsXP操作系统,VC6.0开发环境。
3.设计方案
3.1程序功能
游戏界面:
1)开始游戏
2)重新开始游戏设置:
3)蛇的颜色(白色)
4)积分(每次吃掉一个食物增加1分)
3.2设计思想
首先,该游戏有两个类,以及一个枚举类型,列举了蛇块移动的四个方向;一个蛇块类,用来描述蛇块的信息和将自身绘制到画布上;另一个是画蛇类,画蛇类里要有开始函数,调用开始函数可以使游戏开始,游戏死亡函数,让游戏会结束,既然是贪吃蛇,就少不了蛇的移动,食物的生成,游戏是动态的,在贪吃蛇吃食物的过程中,每吃一个界面就需要更新一下,当然需要用到定时更新函数和刷新画板,保持游戏的动态和连贯性。
大概思想是这样的,里面需要注意的是,蛇什么情况下死亡,有两种情况,第二,舌头蛇尾相接。
蛇在移动时,如果遇到食物,就把食物吃了,蛇的身子会长一节,如果前方没有食物,就响应键盘,按照方向移动。
蛇可以沿着墙壁走,但是沿着墙壁走和撞墙是有区别的,这些细节要区分开。
其次,设计主界面,即一个Form框,在框里放一个PictureBox框,设置画布类来作为贪吃蛇游戏的背景。
界面里要有开始按钮,暂停、重新开始、退出这些按钮。
开始就是要初始化并加载游戏,暂停是当游戏在进行时,可以短时间内终止,重新开始,是继续暂停时的游戏,退出要将该游戏系统关闭,便可以退出。
为了满足游戏的动态画面效果和适应不同级别的人群,要设置游戏蛇块颜色的菜单,食物颜色的菜单,以及游戏等级菜单,来最大可能地满足不同需求的人群,扩大市场的需求,为了更细心体贴,再设置一个帮助菜单更好,引导人们更方便地使用一些功能。
大体上就是这样吧,有了思想在敲打代码的过程中就有了目标,思路会清晰,不过一些细节性的问题要注意。
3.3设计总体流程图
3.4设计的具体实现
1)、蛇块类
把蛇分成一块一块,一个蛇相当于有若干个块,蛇块类就是用来描述每块的信息。
a)、蛇块类的私有变量:
b)、获取记录蛇块的坐标:
publicPointPoint//属性
c)、Paint函数:
publicvirtualvoidPaint(Graphicsg)
Paint函数根据坐标以及蛇块大小计算出实际绘图的坐标,进行绘图,蛇块是一个正方形(矩形),我们用矩形绘制,在代码中我们看到,绘制的大小比size小1个像素,这么做的原因是为了突出蛇块与蛇块之间的间隙,也就是说蛇块与蛇块之间有1个像素的间隙,这就是我们看到游戏效果图中的蛇块是一段一段的原因。
2)、画蛇类
画蛇类是真个游戏的核心处理类,里面定义了画布的大小,背景色,蛇块列表以及游戏速度,移动方向等属性另外还提供了timer计时器,用于定时更新蛇块坐标位置,以及如何在画面上画图的函数。
a)、Start函数用于开始游戏,这个函数的内部其实就是设定食物,以及触发计时器。
这里面定义了计时器的事件触发间隔,是通过level然后找到speed数组里的对应毫秒值设定的。
然后触发事件是OnBlockTimedEvent,最后是启动计时器开始计时。
b)、GetFood函数用于生成下一个食物,其实就是一个蛇块,生成的规则就是,坐标要在画布范围内,并且食物的坐标不能和贪吃蛇的坐标重合,具体代码如下通过for循环检查食物坐标是否和贪吃蛇的蛇块列表ArrayList里的蛇块有冲突。
c)、Move函数用于更新整个蛇块的坐标,我们前面通过将蛇块信息放到ArrayList里来表示贪吃蛇的整个信息,其中根据下标从0到Count-1依次表示各个蛇块的信息,实际代码中增加了吃食物的情况判断,也就是说如果新蛇头的坐标和食物的坐标一致,那么就不做删除原蛇尾的操作了,这样产生的效果就是蛇块列表的长度增加了一个,达到吃食物变长的效果。
f)、PaintPalette函数需要一个参数,也就是绘图句柄,然后在这个画布上画图也就是我们看到的游戏效果,首先用背景色清空画布,然后画食物,其次是通过for循环将贪吃蛇的每个蛇块画在画布上,以此达到游戏效果。
g)、构造函数很简单就是设定类属性值,还有初始化蛇块列表ArrayList,然后需要说明的是你得手动生成一个蛇块放到列表里面,否则连个蛇头都没有怎么玩啊。
this._blocks.Insert(0,(newBlock(Color.Red,this._size,newPoint(width/2,height/2))));
这句话就是在画布的正中央产生一个只有一节的贪吃蛇。
4.程序测试
4.1测试内容与结果
游戏方面:
1)开始:
程序运行后,会出来只有一节的红色蛇和一个黄色的食物,并且蛇是静止的。
点击开始按钮后,红色的蛇开始运动。
所以开始按钮使用正确。
2)方向键和WSAD键:
蛇开始运行之后,当点击上下左右键(或WSAD)蛇就会按相应的方向运动,由于现实中蛇不会180度的转弯,所以就进行设置,让蛇块只能进行90度的转弯。
程序检测时蛇确实会按点击方向运动且不会向相反方向运动,所有方向键使用正确。
3)暂停/继续:
当程序正在运行时,点击暂停/继续按钮,蛇停在当前的位置,再次点击蛇又从当前位置继续运动。
此按钮符合要求,所以暂停/继续按钮使用正确,功能能够实现。
4)重新开始:
当游戏结束或想重新开始一局时,点击此按钮,游戏又回到最初的状态,一个食物,一个运动着的红色蛇块,且游戏积分清零。
所以重新开始功能能够实现。
5)退出:
点击退出按钮,游戏窗口关闭,回到程序界面。
所以退出功能可以实现。
游戏设置:
)积分:
当蛇吃了一块食物后,并且当游戏结束之后会弹出一个对话框,显示游戏结束和总积分。
.实验总结
通过这次试验,让我学到很多这个学期没有接触过的很多知识,完成一个贪吃蛇的项目;第一步就是先理清思路,设计主界面,主界面是以一具封闭的画布,并在画布的设计蛇体和食物。
蛇头如果碰到墙或者与蛇身的某一部分碰到就会死亡;如果蛇头碰到食物,就会自动增加一节蛇身,并更改得分。
想要写出好的程序,还是要有扎实的基础,这样遇到问题就不会一筹莫展来。
在编程时我们要有想象力,不要拘泥于现有的贪吃蛇游戏,而是要把自己想到的再加上所学的知识,遇到问题不能怕,而是要专心找出问题的原因,再回来看看书本的知识,不懂的还可以问问老师。
编程过程还要养成良好的编程习惯,这样不仅自己能够很好看懂自己的代码,也让人家容易看懂自己的代码,而不至于代码知识自己会看,出来问题只有自己会解决而其他人都不会解决;遇到问题时要考虑最简单的解决方案,只有简单的方案不能满足要求时再考虑复杂的方案。
最主要编程还是要多与人沟通,不会的不能立即问别人,但是一段时间后解决不了时还是应该向别人请教请教,“三人行必有我师”正是这个意思。
通过这次实验,我深刻地体会到了面向对象与面向过程的区别。
程序在最初设计时由于面向对象的思想不够成熟,导致在最后想要增加一些新的功能时,出现了一些麻烦,
附录A:
主要源程序
#include
#include
#include
#include
structNode//双向链表用来存储蛇身体
{
intx;
inty;//x,y为蛇身体每个块的横纵坐标
structNode*pre;
structNode*next;
};
structFood
{
intx;
inty;
charc;
};
voidstart()
{
system("cls");
system("color0a");//改变背景及字体颜色
printf("**********************************\n");
printf("**\n");
printf("*贪吃蛇*\n");
printf("**\n");
printf("**\n");
printf("*按wasd控制蛇移动方向*\n");
printf("*按回车键开始游戏*\n");
printf("**\n");
printf("**********************************\n");
}
voidmain()
{
inta[15][15]={0},score=0;
inti,j,t,flag=0;
charc='d',c1='d',f;
structFoodfood={5,8,'A'};
intgameover=0;
structNode*head,*p,*rear,*pt;
head=(structNode*)malloc(sizeof(structNode));//初始化蛇头的位置
head->x=5;
head->y=8;
head->pre=NULL;
head->next=NULL;
rear=head;
start();
getchar();
srand((unsigned)time(NULL));//初始化随机数种子
while
(1)
{
if(food.x==head->x&&food.y==head->y)
{
p=(structNode*)malloc(sizeof(structNode));
pt=head;
while(pt->next!
=NULL)
pt=pt->next;
p->pre=pt;
pt->next=p;
p->next=NULL;
rear=p;
food.x=rand()%15;
food.y=rand()%15;
food.c=1;
flag=1;
t=0;
while(flag==1)//随机产生食物
{
if(t>5)
break;
flag=0;
pt=head;
while(pt!
=NULL)
{
if(food.x==pt->x&&food.y==pt->y)
{
flag=1;
food.x=rand()%15;
food.y=rand()%15;
break;
}
pt=pt->next;
}
t++;
}
if(t>5)//控制蛇的移动
{
if(c=='d')
{
food.x=head->x+1;
food.y=head->y;
if(food.x>=15)
food.x-=15;
}
elseif(c=='a')
{
food.x=head->x-1;
food.y=head->y;
if(food.x<0)
food.x+=15;
}
elseif(c=='w')
{
food.x=head->x;
food.y=head->y+1;
if(food.y>=15)
food.y-=15;
}
elseif(c=='s')
{
food.x=head->x;
food.y=head->y-1;
if(food.y<0)
food.y+=15;
}
}
}
if(kbhit())
{
c1=getch();
if(c1==27)
break;
if(c!
='d'&&c1=='a')
c=c1;
elseif(c!
='a'&&c1=='d')
c=c1;
elseif(c!
='w'&&c1=='s')
c=c1;
elseif(c!
='s'&&c1=='w')
c=c1;
}
pt=rear;
while(pt!
=head)
{
pt->x=pt->pre->x;
pt->y=pt->pre->y;
pt=pt->pre;
}
if(c=='d')
{
head->y+=1;
if(head->y>=15)
head->y-=15;
}
elseif(c=='a')
{
head->y-=1;
if(head->y<0)
head->y+=15;
}
elseif(c=='w')
{
head->x-=1;
if(head->x<0)
head->x+=15;
}
elseif(c=='s')
{
head->x+=1;
if(head->x>=15)
head->x-=15;
}
pt=head->next;
while(pt!
=NULL)//判断蛇头是否咬到自己
{
if(head->x==pt->x&&head->y==pt->y)
{
gameover=1;
break;
}
pt=pt->next;
}
if(gameover==1)
break;
system("color0e");
system("cls");
printf("───────────────\n");
for(i=0;i<15;i++)
{
printf("│");
for(j=0;j<15;j++)
{
flag=0;
pt=head;
while(pt!
=NULL)//输出当前行的蛇身体
{
if(i==pt->x&&j==pt->y)
{
if(pt==head)
printf("■");
else
printf("□");
flag=1;
break;
}
pt=pt->next;
}
if(flag==0)//输出食物
{
if(i==food.x&&j==food.y)
{
putchar(food.c);
putchar('');
continue;
}
printf("");
}
}
printf("│");
putchar('\n');
}
printf("───────────────\n");
_sleep(200);
}
if(gameover==1)
{
p=head;
while(p->next!
=NULL)
{
score++;
p=p->next;
}
system("color0e");
system("cls");
printf("**********************************\n");
printf("*你的得分为%3d*\n",score);
printf("*游戏结束*\n");
printf("*是否重新开始游戏(y/n):
*\n");
printf("**********************************\n");
}
scanf("%c",&f);
if(f=='y')
main();
}