贪吃蛇实验报告.docx
- 文档编号:5645229
- 上传时间:2022-12-30
- 格式:DOCX
- 页数:24
- 大小:368.07KB
贪吃蛇实验报告.docx
《贪吃蛇实验报告.docx》由会员分享,可在线阅读,更多相关《贪吃蛇实验报告.docx(24页珍藏版)》请在冰豆网上搜索。
贪吃蛇实验报告
实验报告
课程名称:
Windows程序设计
实验名称:
贪吃蛇
设计成员:
漆咏康彭哲李佩东程焱桥
康勇周涛高志奇
专业年级:
2011级软件工程
填写时间:
2012/12/24
贪吃蛇
一所要实现贪吃蛇的功能:
1、点击“上”、“下”、“左”、“右”,蛇想相应的方向移动;每吃到一个豆子,蛇的长度增加一个,然后又生成一个食物;当蛇撞界或者吃到自己时,游戏结束并显示“GAMEOVER”;蛇每吃一个食物,右边得分就增加;
2、在右边区域显示此游戏的作者姓名;
3、去掉工具栏,将应用程序的图标和名称改变;
4、当点击游戏菜单下的“新游戏”、“游戏开始”、“游戏暂停”、“游戏继续”相关按钮时,就会执行相应的功能;
5、当点击音效菜单下的“开启声音”、“关闭声音”时,就会响起声音或者关闭声音;
6、当在难度设置菜单下设置了难度后,游戏的难度就会做相应的变化;
7、当不了解游戏规则时,单击帮助菜单下的“游戏规则说明”就会弹出一个消息框;
相关界面如下:
二贪吃蛇的设计思想:
1、界面布局的实现:
采用图形工具(位图、画笔、文本文字)在单文档上显示出来;装载应用程序图标及修改应用程序图标;修改菜单栏以及去掉工具栏并固定应用程序窗口大小,取消最大化;
2、在视类源文件定义一个蛇类和食物类的结构体变量,并初始化蛇的各项成员变量,包括蛇出现在客户区的初始位置、长度以及蛇的行驶方向;同时也要初始化食物类:
食物出现的初始位置以及食物是否被吃掉的判断;用初始化长度为3的蛇,并且默认食物为0,未出现;
3、为视类添加一个公共成员变量,用来存放分数;在视类源文件处定义一个静态变量,用来存放时间time1;
4、给视类添加一个WM_TIMER消息,用OnTimer()函数不断更新游戏;同时也要添加一个WM_KEYDOWN,用OnKeyDown()来响应玩家的实际操作;另外,也要添加一个WM_RBUTTONDOWN消息,此消息只是为了获取客户区相应位置的位置,用于显示文字而用;
5、具体游戏实现,还要包括蛇撞到墙或吃到自己都会结束游戏并输出“GAMEOVER”,显示得分,还有判断吃豆以及通过时间来改变游戏的难度。
注:
我们小组的贪吃蛇设计实现全部是在视类中实现的,在其它类不要添加代码;
我们主要用到的知识点有:
视类的消息响应、菜单栏的消息响应、结构体变量及数组、CDC类画图
三实验具体步骤:
1、打开VisualC++新建一个单文档应用程序,默认工程名文件夹为Snake3
2、然后为视类添加3个消息映射,WM_KEYDOWN、WM_RUTTONDOWN、WM_TIMER;同时为视类增加一个消息OnInitialUpdate()用来初始化;
3、为视类添加一个公共成员变量soure,存放分数;为视类添加2个成员函数oninit()和grade(),分别用来贪吃蛇的外观的初始化以及显示分数而用;
4、在视类源文件开头定义一个静态变量time1=500,存放时间;然后构造一个蛇类和食物类;
5、引入图标和位图,用于修改应用程序图标和添加围墙;
6、更改应用程序图标和名称,去掉工具栏,修改菜单栏;图形如下:
7、为个菜单项添加消息映射如下:
新游戏:
IDM_REOPENOnReopen()
游戏开始:
IDM_STARTOnStart()
游戏暂停:
IDM_PAUSEOnPause()
游戏继续:
IDM_CONTINUEOnContinue()
游戏退出:
IDM_EXITOnExit()
开启声音:
IDM_SOUND_OPENOnSoundOpen()
关闭音效:
IDM_SOUND_CLOSEOnSoundClose()
简单:
IDM_SIMPLEOnSimple()
中等:
IDM_MIDDLEOnMiddle()
困难:
IDM_DIFFICULTOnDifficult()
游戏规则说明:
IDM_SHUOMINGOnShuoming()
8、取消最大化按钮并固定应用程序窗口大小,如下
9、在右边显示文字,如下
10、添加背景位图、砖并画出白色游戏区
11、具体代码实现
12、调试并修改错误
13、完成实验并写实验报告
注:
视类中添加函数如下:
两个类:
四实验代码及功能解释:
1、intCMainFrame:
:
OnCreate(LPCREATESTRUCTlpCreateStruct)
{
//装载应用程序图标
HICONhIcon=AfxGetApp()->LoadIcon(IDI_ICON1);
SetClassLong(m_hWnd,GCL_HICON,(long)hIcon);
//去掉工具栏
ShowControlBar(&m_wndToolBar,FALSE,FALSE);
return0;
}
2、BOOLCMainFrame:
:
PreCreateWindow(CREATESTRUCT&cs)
{
if(!
CFrameWnd:
:
PreCreateWindow(cs))
returnFALSE;
//TODO:
ModifytheWindowclassorstylesherebymodifying
//theCREATESTRUCTcs
//使窗口不含“最大化”按钮
cs.hMenu=LoadMenu(AfxGetApp()->m_hInstance,MAKEINTRESOURCE(IDR_MAINFRAME));
cs.style&=~WS_THICKFRAME;
cs.style&=~WS_MAXIMIZEBOX;
//设置用程序窗口的大小,使其固定大小
CRectrect;
rect.SetRect(10,10,750,550);
AdjustWindowRect(&rect,cs.style,TRUE);
cs.cx=rect.right-rect.left;
cs.cy=rect.bottom-rect.top;
returnTRUE;
}
3、CSnackView:
:
CSnackView()
{
//TODO:
addconstructioncodehere
//装载一个背景位图
CBitmapbmp;
bmp.LoadBitmap(IDB_BITMAP3);
m_brushBackground.CreatePatternBrush(&bmp);
soure='0';//初始化用来显示分数的字符串变量soure,使分数开始为0
}
4、voidCSnackView:
:
OnDraw(CDC*pDC)
{
CSnackDoc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
//TODO:
adddrawcodefornativedatahere
//使背景位图显示在整个客户区内
CRectrect;
GetClientRect(rect);
pDC->FillRect(rect,&m_brushBackground);
//画出游戏区,用位图
CBitmapm_bmp2;
m_bmp2.LoadBitmap(IDB_BITMAP7);
BITMAPbm2;
m_bmp2.GetObject(sizeof(BITMAP),&bm2);
CDCdc2;
dc2.CreateCompatibleDC(pDC);
CBitmap*pOldbmp2=dc2.SelectObject(&m_bmp2);
for(inti=20;i<=480;i=i+20)
for(intj=20;j<=480;j=j+20)
pDC->BitBlt(i,j,bm2.bmWidth,bm2.bmHeight,&dc2,0,0,SRCCOPY);
dc2.SelectObject(pOldbmp2);
//在右边添加文字
CFontfont;
font.CreateFont(19,0,0,0,FW_NORMAL,FALSE,FALSE,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH|FF_SWISS,_T("黑体"));
CFont*pOldFont=pDC->SelectObject(&font);
COLORREFoldColor=pDC->SetTextColor(RGB(255,255,255));
intoldMode=pDC->SetBkMode(TRANSPARENT);
pDC->TextOut(560,289,_T("作者:
"));
pDC->TextOut(574,320,_T("漆咏康"));
pDC->TextOut(574,349,_T("彭哲"));
pDC->TextOut(574,380,_T("李佩东"));
pDC->TextOut(574,410,_T("程焱桥"));
pDC->TextOut(574,440,_T("康勇"));
pDC->TextOut(574,470,_T("周涛"));
pDC->TextOut(574,495,_T("高志奇"));
pDC->SetTextColor(oldColor);
pDC->SetBkMode(oldMode);
pDC->SelectObject(pOldFont);
//添加周围砖块
CBitmapm_bmp;
m_bmp.LoadBitmap(IDB_BITMAP2);
BITMAPbm;
m_bmp.GetObject(sizeof(BITMAP),&bm);
CDCdc;
dc.CreateCompatibleDC(pDC);
CBitmap*pOldbmp=dc.SelectObject(&m_bmp);
for(inti=0;i<=500;i=i+20)
pDC->BitBlt(0,i,bm.bmWidth,bm.bmHeight,&dc,0,0,SRCCOPY);
for(i=0;i<=500;i=i+20)
pDC->BitBlt(i,0,bm.bmWidth,bm.bmHeight,&dc,0,0,SRCCOPY);
for(i=0;i<=500;i=i+20)
pDC->BitBlt(i,500,bm.bmWidth,bm.bmHeight,&dc,0,0,SRCCOPY);
for(i=0;i<=500;i=i+20)
pDC->BitBlt(500,i,bm.bmWidth,bm.bmHeight,&dc,0,0,SRCCOPY);
dc.SelectObject(pOldbmp);
//调用oninit()函数来画处蛇,并在右边显示“得分”字样,同时初始化得分为0
oninit();
}
5、voidCSnackView:
:
OnKeyDown(UINTnChar,UINTnRepCnt,UINTnFlags)
{
//TODO:
Addyourmessagehandlercodehereand/orcalldefault
//nChar为键盘字符,此函数为键盘字符按下消息映射
//1代表“上”,2代表“下”,3代表“左”,4代表“下”
switch(nChar)
{
caseVK_UP:
if(Snake[0].direct!
=2)Snake[0].direct=1;break;//当方向不是下的,才使得按下“上“时,方向为上,也就是当蛇的方向向上时,使向下的操作无效
caseVK_DOWN:
if(Snake[0].direct!
=1)Snake[0].direct=2;break;//当方向不是上的时候才能向下
caseVK_LEFT:
if(Snake[0].direct!
=4)Snake[0].direct=3;break;//当方向不是右的时候才能向左
caseVK_RIGHT:
if(Snake[0].direct!
=3)Snake[0].direct=4;break;//当方向不是左的时候才能向右
}
CView:
:
OnKeyDown(nChar,nRepCnt,nFlags);
}
6、voidCSnackView:
:
OnRButtonDown(UINTnFlags,CPointpoint)
{
//TODO:
Addyourmessagehandlercodehereand/orcalldefault
//此函数对游戏没有实际作用,只是为了获得客户区的坐标
CStringstr;
str.Format("%d,%d",point.x,point.y);
AfxMessageBox(str);
CView:
:
OnRButtonDown(nFlags,point);
}
7、voidCSnackView:
:
OnTimer(UINTnIDEvent)
{
//TODO:
Addyourmessagehandlercodehereand/orcalldefault
//定义一个字符串用来存放分数,每吃一个食物得10分
soure.Format("%d",(Snake[0].len-2)*10);
//提前设置好要显示文字的属性,为后面游戏结束时显示"GAMEOVER"用
CDC*pDC=GetDC();
CFontfont;
font.CreateFont(95,0,0,0,FW_NORMAL,FALSE,FALSE,0,ANSI_CHARSET,
OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH|FF_SWISS,_T("黑体"));
CFont*pOldFont=pDC->SelectObject(&font);
COLORREFoldColor=pDC->SetTextColor(RGB(255,0,0));
intoldMode=pDC->SetBkMode(TRANSPARENT);
//撞界判断,撞了之后就显示"GAMEOVER"
//当蛇撞界或者吃到自己时为什么都会有4条if语句,这时由于代码原因,当撞界或者吃到自己时也会向前进一格
//由于蛇的移动是这样实现的,每移动一格,也就是蛇头移动一格,蛇身全部移动一格,然后把最后一格用白色给覆盖,看起来就像走了一格
//所以当撞界或是吃到自己的时候,为了让蛇不再前进一格,也就是把蛇头画在蛇尾,这样看起来就像没动一样
if(Snake[0].x*20==20)//当蛇快要撞到左侧的墙时,如果方向仍然为左,则撞墙了
{
if(Snake[0].direct==3)
{
KillTimer
(1);
Snake[0].x=Snake[Snake[0].len-1].x+1;
Snake[0].y=Snake[Snake[0].len-1].y;
pDC->TextOut(40,222,_T("GAMEOVER"));//显示"GAMEOVER"
}
}
if(Snake[0].y*20==20)//当蛇快要撞到上侧的墙时,如果方向仍然为上,则撞墙了
{
if(Snake[0].direct==1)
{
KillTimer
(1);
Snake[0].y=Snake[Snake[0].len-1].y+1;
Snake[0].x=Snake[Snake[0].len-1].x;
pDC->TextOut(40,222,_T("GAMEOVER"));
}
}
if(Snake[0].y*20==480)//当蛇快要撞到下侧的墙时,如果方向仍然为下,则撞墙了
{
if(Snake[0].direct==2)
{
KillTimer
(1);
Snake[0].y=Snake[Snake[0].len-1].y-1;
Snake[0].x=Snake[Snake[0].len-1].x;
pDC->TextOut(40,222,_T("GAMEOVER"));
}
}
if(Snake[0].x*20==480)//当蛇快要撞到右侧的墙时,如果方向仍然为上右,则撞墙了
{
if(Snake[0].direct==4)
{
KillTimer
(1);
Snake[0].x=Snake[Snake[0].len-1].x-1;
Snake[0].y=Snake[Snake[0].len-1].y;
pDC->TextOut(40,222,_T("GAMEOVER"));
}
}
//蛇头吃到自己判断,如果吃到了,则显示"GAMEOVER"
for(inti=Snake[0].len-1;i>0;i--)
{
if(Snake[0].x*20==Snake[i].x*20&&Snake[0].y*20==Snake[i].y*20)
{
if(Snake[0].direct==3)
{
KillTimer
(1);
Snake[0].x=Snake[Snake[0].len-1].x+1;
Snake[0].y=Snake[Snake[0].len-1].y;
}
if(Snake[0].direct==1)
{
KillTimer
(1);
Snake[0].y=Snake[Snake[0].len-1].y+1;
Snake[0].x=Snake[Snake[0].len-1].x;
}
if(Snake[0].direct==2)
{
KillTimer
(1);
Snake[0].y=Snake[Snake[0].len-1].y-1;
Snake[0].x=Snake[Snake[0].len-1].x;
}
if(Snake[0].direct==4)
{
KillTimer
(1);
Snake[0].x=Snake[Snake[0].len-1].x-1;
Snake[0].y=Snake[Snake[0].len-1].y;
}
pDC->TextOut(40,222,_T("GAMEOVER"));
}
}
/此段代码就是上面说的,为了让蛇移动一步,就是把蛇尾用背景位图给擦去
CBitmapm_bmp2;
m_bmp2.LoadBitmap(IDB_BITMAP7);
BITMAPbm2;
m_bmp2.GetObject(sizeof(BITMAP),&bm2);
CDCdc2;
dc2.CreateCompatibleDC(pDC);
CBitmap*pOldbmp2=dc2.SelectObject(&m_bmp2);
pDC->BitBlt(Snake[Snake[0].len-1].x*20,Snake[Snake[0].len-1].y*20,bm2.bmWidth,bm2.bmHeight,&dc2,0,0,SRCCOPY);
dc2.SelectObject(pOldbmp2);
for(i=Snake[0].len-1;i>0;i--)
{
Snake[i].x=Snake[i-1].x;
Snake[i].y=Snake[i-1].y;
}
//行走方向判断,向哪个方向,蛇头就向那个方向移动一格
if(Snake[0].direct==1)Snake[0].y--;
if(Snake[0].direct==2)Snake[0].y++;
if(Snake[0].direct==3)Snake[0].x--;
if(Snake[0].direct==4)Snake[0].x++;
//当向哪个方向时,就向前画一个蛇头
//当向哪个方向时,就向前画一个蛇头
CBitmapm_bmp4;
m_bmp4.LoadBitmap(IDB_BITMAP5);
BITMAPbm4;
m_bmp4.GetObject(sizeof(BITMAP),&bm4);
CDCdc4;
dc4.CreateCompatibleDC(pDC);
CBitmap*pOldbmp4=dc4.SelectObject(&m_bmp4);
pDC->BitBlt(Snake[0].x*20,Snake[0].y*20,bm4.bmWidth,bm4.bmHeight,&dc4,0,0,SRCCOPY);
pDC->SelectObject(pOldbmp4);
//判断吃豆的条件,撞到就吃
if(Snake[0].x*20==Food.x*20&&Snake[0].y*20==Food.y*20)
{
Snake[0].len++;//吃到了长度自然要加1
Food.isfood=0;//吃豆后食物就没了,赋值为1
//吃到了就增加一个蛇身
Snake[Snake[0].len-1].x=Snake[Snake[0].len-2].x;
Snake[Snake[0].len-1].y=Snake[Snake[0].len-2].y;
//吃到了分数就要增加,调用grade()函数动态显示
grade();
}
//如果食物被吃了就再生成一个食物
if(Food.isfood==0)
{
srand((unsigned)time(NULL));//用于产生随机值,是每次产生的一组随机数都不同
Food.x=(rand()%(25-1))+1;//产生[1,25)范围内的整数
Food.y=(rand()%(25-1))+1;//产生[1,25)范围内的整数
//这两个循环用来判断当食物产生在蛇身上时,重新产生一个随机数
for(inti=0;i<=Snake[0].len-1;i++)
{
if(Food.x==Snake[i].x&&Food.y==Snake[i].y)
{
Food.x=(rand()%(25-1))+1;
Food.y=(rand()%(25-1))+1;
}
}
for(i=Snake[0].len-1;i>=0;i--)
{
if(Food.x==Snake[i].x&&Food.y==Snake[i].y)
{
Food.x=(rand()%(25-1))+1;
Food.y=(rand()%(25-1))+1;
}
}
//产生一个食物
CBitmapm_bmp;
m_bmp.LoadBitmap(IDB_BITMA
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 贪吃 实验 报告
![提示](https://static.bdocx.com/images/bang_tan.gif)