贪吃蛇c++实验报告Word文档下载推荐.docx
《贪吃蛇c++实验报告Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《贪吃蛇c++实验报告Word文档下载推荐.docx(15页珍藏版)》请在冰豆网上搜索。
OnYsExit()//退出游戏(菜单响应消息)
OnYsEffect()//控制游戏音效
OnYsMusicbkg()//控制游戏背景音乐
OnYsLevel1()//控制游戏等级为初级
OnYsLevel2()//控制游戏等级为中级
OnYsLevel3()//控制游戏等级为高级
OnYsHelpgame()//游戏帮助
OnYsBest()//英雄榜的显示
3.1.2变量声明
CArray<
CPoint,CPoint>
m_ysBody;
//定义点数组作为蛇的身体
CPointm_ysFood;
//食物出现的点
intm_ysTime;
//显示时间
intm_ysTime1;
//满10则进一位使时间增加1秒
intm_ysDirect;
//方向控制变量
intm_ysScore;
//玩家成绩变量
intm_yspausectrl;
//暂停控制变量
intm_yslevelctrl;
//等级控制变量
CStringm_ysPlayer;
//玩家姓名
intm_yseffectctrl;
//音效控制变量
intm_ysmusicctrl;
//背景音乐控制变量
3.1.3资源
1、对话框
IDD_YS_HELPGAME//游戏帮助说明
IDD_YS_BEST//英雄榜
IDD_YS_RETRY//停止游戏确认
IDD_ABOUTBOX//关于游戏版本
2、音乐
IDR_YS_BKGMUSIC//游戏背景音乐
IDR_YS_EAT//贪吃蛇吃到食物的音乐
IDR_YS_LOWSCORE//游戏结束后得低分音乐
IDR_YS_HIGHSCORE//游戏结束后得高分音乐
3、位图
IDB_YS_BITMAP//游戏背景图
4、菜单/工具栏
IDR_MAINFRAME//系统自带菜单
IDR_YS_TOOLBAR//自己创建的工具条
5、头文件
mmsystem.h//播放音乐的相应文件
fstream.h//文件流文件
3.2主要功能的实现
3.2.1游戏界面
贪吃蛇游戏的游戏界面包括背景图片、蛇身体的绘制、蛇移动范围的绘制等等。
其中贪吃蛇的身体用什么方法绘制,才可以使得其在游戏过程中可以实现“吃”的功能是很重要的。
因此在游戏界面的初始绘制时就必须考虑到游戏时可能遇到的问题。
本程序采用点数组CArray<
m_ysBody来存储贪吃蛇,点数组的功能很强大,可以添加点,同时可以获得蛇的长度,对于而后进行游戏中控制蛇的颜色以及音效的播放等都有很大的帮助。
3.2.2初始化食物
确定用点数组存储贪吃蛇以后,贪吃蛇的食物如何达到随机出现,并且能够按照网格式与蛇头无偏差相接就是一个亟待解决的问题。
随机出现应采用rand()函数来实现,而食物与蛇头无偏差相接则利用坐标来解决。
设置两个整型变量m_ysX,m_ysY作为食物出现的点的坐标,令m_ysX=rand()%30,,m_ysY=rand()%40即可。
使随机出现的点能够整除最小网格,也就是使食物与蛇头无偏差相接。
再由食物坐标(m_ysX,m_ysY)与蛇头坐标是否相同判断蛇是否“吃”到了食物,设置判断标签ysTag,如果吃到了,ysTag为1,则再出现下一个食物,反之,如果没吃到,则不出现食物直到标签为1为止。
最后,再将(m_ysX,m_ysY)赋给m_ysFood作为食物坐标,以便在其他函数中调用。
蛇的身体是与出现的食物在一条直线上的,完全可以达到相接的目的。
3.2.3开始游戏
开始游戏后的重点是如何用键盘来控制蛇的移动并传递到OnTimer(UINTnIDEvent)函数中去以及判断蛇是否死亡。
首先说明键盘与蛇的响应,设置一个方向控制变量m_ysDirect,再添加OnKeyDown(UINTnChar,UINTnRepCnt,UINTnFlags)函数来实现键盘消息的传递,按下不同的键盘按键,m_ysDirect会相应的改变,再利用switch语句在OnTimer(UINTnIDEvent)函数中对坐标进行相应改变即可。
其次来解释一下如何判断蛇的死亡,由于蛇的身体是由点坐标数组构成的,因此判断蛇是否死亡其本质就是判断蛇头的坐标是否与游戏边框相同或者蛇头坐标是否与蛇自己的身体相同。
该过程也在OnTimer(UINTnIDEvent)函数中写入即可,设置一个判断死亡变量ysTag1,当按下向下键时,蛇纵坐标不断自加,此处仅以向下为例,具体程序如下:
switch(m_ysDirect)//根据键盘按下键来选择蛇移动的方向
{
case1:
//方向变量向下
ysPoint2.y++;
//点纵坐标自加
if(ysPoint2.y>
=40)//如果纵坐标多于最下端边框
{
ysTag1=1;
//变量为1,判断死亡
}
break;
}
如果ysTag1为1,则说明蛇已经死亡,应当弹出对话框提示死亡,输出得分,同时还可以根据玩家的得分数相应的改变对话框中的话语(XP系统下)。
我们看到图3-4的蛇身体的颜色发生了变化,不再是初始状态的绿色,而是变为了蓝色,这是在OnDraw(CDC*pDC)函数中设置的,设置变量获取蛇身长度,随着长度的增加,蛇的颜色发生相应改变,最终会变为表示危险的红色。
并且伴随着贪吃蛇挂掉,播放不同的音乐,如果高于70分,则放带有掌声鼓励的高分音乐的IDR_YS_HIGHSCORE,反之,则播放蛇被撞死的电子音乐IDR_YS_LOWSCORE。
播放音乐的函数用包含在头文件mmsystem.h中的PlaySound函数。
此外,游戏开始还需要计时、计分以及暂停等功能。
这些功能都比较简单,游戏时间和分数分别用两个变量m_ysTime和m_ysScore来记录,应用pDC->
TextOut函数来输出即可。
至于暂停和继续的功能实现,只需要暂停和恢复计时器就可以了,实现暂停功能即KillTimer
(1)并同时令控制暂停变量为m_yspausectrl为0即可。
3.2.4英雄榜
很多游戏都有英雄榜这一个功能。
贪吃蛇这个游戏也不例外,为了下一次开始新游戏的玩家也能够看到别人的成绩,所以采用文件来存储游戏记录。
首先加入头文件fstream.h包含文件写入读出函数ifstream、ofstream。
定义文件及变量存储成绩,将对话框中EditBox的变量设置成为对应类型。
例如:
CYsBestRecorddlg;
dlg.m_ysbestscore1=m_1bestscore;
上面所写的就是变量的传递,传递完毕后,对话框控件中就有了初值,可以正常显示分数。
而后进行游戏相应等级的玩家成绩判断,如果玩家成绩与英雄榜成绩相同,则根据时间来判断,若游戏时间短,则进入英雄榜。
判断条件如下:
(m_ysScore>
m_1bestscore||m_ysScore==m_1bestscore&
&
m_ysTime<
m_1besttime)&
m_yslevelctrl==1
本程序默认游戏结束即显示英雄榜,但玩家如果想在没有游戏时查看也可以点击菜单“帮助—〉英雄榜”查看。
3.2.5游戏设置
这里的游戏设置主要是指游戏的等级以及音效音乐的播放控制。
前面在变量声明中已经看到,关于这三个量,我们已经予以了定义,只需要在按下相应键盘或鼠标消息的时候,将变量值进行改变,再利用这些值控制相应功能的运行。
以游戏音效为例,在按下菜单中的“游戏设置—〉音乐—〉音效开/关”后(即菜单消息voidCYuShuoView:
OnYsEffect()),代码如下:
switch(m_yseffectctrl)//根据音效控制变量选择
//音效选择开
m_yseffectctrl=0;
//将音效控制变量改为0
case0:
//音效选择关
m_yseffectctrl=1;
//将音效控制变量改为1
其中在构造函数CYuShuoView:
CYuShuoView()中已经将m_yseffectctrl的初值设置为1。
4、实验代码
#include<
iostream.h>
windows.h>
stdlib.h>
conio.h>
time.h>
//使用当前时间做种子;
enumdir{up,down,left,right};
//枚举类型enumdir;
//围墙;
classFence{
public:
voidInitFence();
voidOutputF();
chargame[20][20];
}f;
//定义对象;
//画框框;
voidFence:
InitFence(){
for(inti=0;
i<
20;
i++)
for(intj=0;
j<
j++){
if(i==0||i==19||j==0||j==19)
game[i][j]='
*'
;
elsegame[i][j]='
'
//显示框框;
OutputF(){
i++){
j++)
cout<
<
game[i][j]<
'
endl;
//蛇结点;
classSnakeNode{
private:
intx,y;
SnakeNode*prior,*next;
voidadd_head(intx,inty);
intget_x();
intget_y();
voiddelete_tail();
}*head=NULL,*tail=NULL;
//插入头结点;
voidSnakeNode:
add_head(intx,inty){
SnakeNode*q=newSnakeNode;
q->
x=x;
q->
y=y;
next=head;
prior=NULL;
if(head)head->
prior=q;
head=q;
if(!
tail)tail=head;
f.game[x][y]='
//f对象可以在定义Fence类时定义;
且Fence类在SnakeNode类前定义;
intSnakeNode:
get_x(){
returnx;
get_y(){
returny;
//删除尾结点;
delete_tail(){
SnakeNode*p=tail;
f.game[tail->
get_x()][tail->
get_y()]='
//把尾结点的坐标表示的'
置为空格;
if(tail==head)
tail=head=NULL;
else{
tail=tail->
prior;
tail->
next=NULL;
deletep;
//move移动;
classmove{
dirpoint;
//枚举变量point:
控制方向;
intfood_x;
intfood_y;
voidmoving();
voidchange_point(char);
//改变方向;
voidget_food();
};
voidmove:
moving(){
inta,b;
a=head->
get_x();
//取得头结点横坐标
b=head->
get_y();
//头结点纵坐标
switch(point){
caseup:
--a;
casedown:
++a;
caseleft:
--b;
caseright:
++b;
if(a==19||b==19||a==0||b==0||game[a][b]=='
){//判断是否撞墙;
"
gameover!
!
exit(0);
if(a==food_x&
b==food_y){//吃food;
head->
add_head(a,b);
get_food();
//插入头结点;
delete_tail();
//删除尾结点;
change_point(charkeydown){
switch(keydown){
case'
w'
point=up;
s'
point=down;
a'
point=left;
d'
point=right;
get_food(){
srand((unsignedint)time(NULL));
//做种子(程序运行时间);
food_x=rand()%18+1;
food_y=rand()%18+1;
f.game[food_x][food_y]='
//main();
intmain(){
Using'
w,s,a,d'
tocontroldirection!
\n\n\n"
//画框框和小蛇;
movem;
f.InitFence();
add_head(4,3);
add_head(4,4);
add_head(4,5);
m.get_food();
f.OutputF();
while(true){
charkeydown=getch();
//getch()返回键盘上读取的字符;
包含头文件<
m.chan
四、实验结果
程序开始运行后会进入游戏界面,但是不会立即进行游戏,单击菜单的“开始”才会开始游戏。
在游戏开始前,玩家可以根据自己的喜好,通过菜单或者工具栏设置游戏等级等。
在游戏过程中,按下Space键就会暂停游戏,再按下Space键则会继续游戏。
开始游戏了,小蛇越来越长,颜色也有所不同了。
颜色的改变预示着游戏的难度加大了,并且,不同的最终得分会产生不同的死亡评语。
在前面的图3-4中显示了贪吃蛇死亡的样子,其中因为该局游戏得分比较低,因此得到的评语是“你才得了这么两分!
”,而如果得分较高,就会得到更好的评语,最好的评语是“牛!
”。
五、实验体会
通过本次实验,我控股了之前学习的知识,如数据结构和c++语言规范,也更加熟练地掌握了MicrosoftVisualC++6.0环境上网配置和操作,但是仍有不足,本程序由于经常调用Invalidate()函数重绘窗口,因此在游戏过程中频闪的非常严重。
查阅了很多资料,双缓冲技术可以解决这个问题,但是如果采用双缓冲技术,暂时还不能克服背景的问题,因为在双缓冲技术的应用中,背景是被强制默认为颜色,而不是图片。
我尝试改变了一下,但是没有成功,所以这个问题还没有解决。
希望老师多给予指导多多给予意见。