c++贪吃蛇课程设计孙迪宇_第1页
c++贪吃蛇课程设计孙迪宇_第2页
c++贪吃蛇课程设计孙迪宇_第3页
c++贪吃蛇课程设计孙迪宇_第4页
c++贪吃蛇课程设计孙迪宇_第5页
已阅读5页,还剩16页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

齐齐哈尔大学计控学院软件工程专业综合实践报告选题名称: 用C+实现贪吃蛇设计 题目类别: 数据结构 姓 名: 孙迪宇 学 号: 班 级: 软件091 指导教师: 李长荣、吴迪 设计时间: 2010年12月 目录第一章 应用程序的介绍- 1 -1.1选题背景- 1 -1.2关于编译软件- 1 -1.3关于兼容性- 1 -第二章 概要设计- 2 -2.1程序结构- 2 -2.2程序流程- 2 -第三章 游戏实现- 3 -3.1游戏界面控制- 3 -3.2初始化食物- 3 -3.3游戏控制- 4 -3.4游戏设置- 4 - 第四章 结果与讨论- 5 -4.1程序运行- 5 -4.2错误调试与分析- 5 -附录- 6 - - 19 -第一章 课题介绍1.1.选题背景贪吃蛇是家喻户晓的益智类小游戏,选择这个题目一是为了将自己的所学知识加以运用,二是一直以来贪吃蛇这个游戏就深深地吸引着我,它的制作方法对于以前的我而言都是很神秘的。我希望通过自己的所学知识把它剖析开来,真真正正的了解它的本质和精髓。虽然我的编程能力不是很强,但是我有信心,在这次学习中我将从实践和实际的项目中提高自己的编程能力。因此我选定了这个题目。1.2关于编译软件本程序采用Microsoft Visual C+6.0的中文版本进行编译。VisualC+6.0是Microsoft公司推出的基于Windows操作系统的可视化C+编程工具,尽管Microsoft公司推出了.NET平台的集成开发环境,但由于其良好的界面和可操作性,加上支持标准C/C+规范,但仍有相当多的编程人员使用VisualC+6.0进行应用系统的开发。1.3关于兼容性本程序经过调试,可以在XP系统下编译运行,也可以在Vista下运行,界面稍有不同,但不影响运行结果。第二章 概要设计2.1程序结构根据分析,贪吃蛇这个程序一共要实现如下几个功能,包括游戏方面开始游戏、暂停游戏以及停止游戏,音乐音效的添加与控制,游戏帮助提示与英雄榜的显示等等。具体的程序结构如下面的图1-1所示。图2-1 贪吃蛇结构图2.2程序流程根据分析后的贪吃蛇结构设计出相应的贪吃蛇流程。贪吃蛇的内容主要包括: 游戏开始,随机出现食物;按下ToolBar中的暂停按钮或Space键可以实现暂停功能;按下帮助键或ToolBar中的“?”键可获得游戏帮助说明;可播放背景音乐和音效并可通过菜单以及ToolBar控制其播放或停止等等。图2-2 贪吃蛇流程图第三章 游戏实现3.1游戏界面控制贪吃蛇游戏的游戏界面包括背景图片、蛇身体的绘制、蛇移动范围的绘制等等。其中贪吃蛇的身体用什么方法绘制,才可以使得其在游戏过程中可以实现“吃”的功能是很重要的。因此在游戏界面的初始绘制时就必须考虑到游戏时可能遇到的问题。本程序采用点数组CArray m_ysBody来存储贪吃蛇,点数组的功能很强大,可以添加点,同时可以获得蛇的长度,对于而后进行游戏中控制蛇的颜色以及音效的播放等都有很大的帮助。3.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.3游戏控制开始游戏后的重点是如何用键盘来控制蛇的移动并传递到OnTimer(UINT nIDEvent)函数中去以及判断蛇是否死亡。首先说明键盘与蛇的响应,设置一个方向控制变量m_ysDirect,再添加OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)函数来实现键盘消息的传递,按下不同的键盘按键,m_ysDirect会相应的改变,再利用switch语句在OnTimer(UINT nIDEvent)函数中对坐标进行相应改变即可。其次来解释一下如何判断蛇的死亡,由于蛇的身体是由点坐标数组构成的,因此判断蛇是否死亡其本质就是判断蛇头的坐标是否与游戏边框相同或者蛇头坐标是否与蛇自己的身体相同。该过程也在OnTimer(UINT nIDEvent)函数中写入即可,设置一个判断死亡变量ysTag1,当按下向下键时,蛇纵坐标不断自加,如果ysTag1为1,则说明蛇已经死亡,应当弹出对话框提示死亡,输出得分(如图3-4),同时还可以根据玩家的得分数相应的改变对话框中的话语(XP系统下)。我们看到蛇身体的颜色发生了变化,不再是初始状态的绿色,而是变为了蓝色,这是在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.4游戏设置这里的游戏设置主要是指游戏的等级以及音效音乐的播放控制。关于这三个量,我们已经予以了定义,只需要在按下相应键盘或鼠标消息的时候,将变量值进行改变,再利用这些值控制相应功能的运行。第四章 结果与讨论4.1程序运行程序开始运行后会进入游戏界面,但是不会立即进行游戏,单击菜单的“开始”才会开始游戏。在游戏开始前,玩家可以根据自己的喜好,通过菜单或者工具栏设置游戏等级等。在游戏过程中,按下Space键就会暂停游戏,再按下Space键则会继续游戏。图4-1所显示的是XP系统下菜单的样式,以及单击菜单开始。开始游戏了,小蛇越来越长,颜色也有所不同了。颜色的改变预示着游戏的难度加大了,并且,不同的最终得分会产生不同的死亡评语。在前面显示了贪吃蛇死亡的样子,其中因为该局游戏得分比较低,因此得到的评语是“你才得了这么两分!”,而如果得分较高,就会得到更好的评语,最好的评语是“牛!”。如果不太会玩贪吃蛇这款游戏,那么可以单击菜单“帮助游戏说明”,寻求帮助。4.2错误调试与分析本程序由于经常调用Invalidate()函数重绘窗口,因此在游戏过程中频闪的非常严重。查阅了很多资料,双缓冲技术可以解决这个问题,但是如果采用双缓冲技术,暂时还不能克服背景的问题,因为在双缓冲技术的应用中,背景是被强制默认为颜色,而不是图片。我尝试改变了一下,但是没有成功,所以这个问题还没有解决。希望老师多多给予意见。附录Main.#include #pragma hdrstopUSERES(Snake.res);USERC(Snake_Res.rc);USEUNIT(UnitSnake.cpp);USEFORM(UnitTest.cpp, FormMain);USEFORM(UnitEnterName.cpp, FormEnterName);USEFORM(UnitAbout.cpp, FormAbout);WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) try Application-Initialize(); Application-CreateForm(_classid(TFormMain), &FormMain); Application-Run(); catch (Exception &exception) Application-ShowException(&exception); return 0;1.#include #pragma hdrstop#include UnitAbout.h#pragma package(smart_init)#pragma resource *.dfmTFormAbout *FormAbout;_fastcall TFormAbout:TFormAbout(TComponent* Owner) : TForm(Owner) LabelProg-Font-Size = 12; LabelHome-Font-Color = clBlue; LabelHome-Font-Style = LabelHome-Font-StyleWindowProc; BnOK-WindowProc = BnOkWndProc; LabelHomeDefProc = LabelHome-WindowProc; LabelHome-WindowProc = LabelHomeWndProc;void _fastcall TFormAbout:LabelHomeClick(TObject *Sender) ShellExecute(Handle,open,LabelHome-Caption.c_str(),0,SW_SHOWNORMAL);void _fastcall TFormAbout:LabelHomeWndProc(Messages:TMessage &Message) if(Message.Msg=CM_MOUSEENTER) LabelHome-Font-Color = clRed; else if(Message.Msg=CM_MOUSELEAVE) LabelHome-Font-Color = clBlue; LabelHomeDefProc(Message);void _fastcall TFormAbout:BnOkWndProc(Messages:TMessage &Message) if(Message.Msg=CM_MOUSEENTER) BnOK-Font-Color = clRed; else if(Message.Msg=CM_MOUSELEAVE) BnOK-Font-Color = clWindowText; BnOKDefProc(Message);2.#include UnitSnake.hTSnakeBuf:TWall TSnakeBuf:Wall0=-1;TSnakeBuf:TWall TSnakeBuf:Wall1=5,10,23,10,-1;TSnakeBuf:TWall TSnakeBuf:Wall2=10,5,10,16,18,5,18,16,-1;TSnakeBuf:TWall TSnakeBuf:Wall3=10,5,10,16,18,5,18,16, 5,10,23,10,-1;TSnakeBuf:TWall TSnakeBuf:Wall4= 5,6,23, 6,5,14,23,14,-1;TSnakeBuf:TWall TSnakeBuf:Wall5= 5,6,23, 6,5,14,23,14,14, 7,14,13,-1;TSnakeBuf:TWall TSnakeBuf:Wall6=10,0,10,16,18,5,18,20,-1;TSnakeBuf:TWall TSnakeBuf:Wall7= 0,6,23, 6,5,14,27,14,-1;TSnakeBuf:TWall TSnakeBuf:Wall8= 6,5, 6,20,20,5,20,20,13, 0,13,16,-1;TSnakeBuf:TWall TSnakeBuf:Wall9= 0,6,15, 6,21,0,21, 9,12,14,27,14,6,12,6,20,-1;TSnakeBuf:TWall *TSnakeBuf:Walls=TSnakeBuf:Wall0,TSnakeBuf:Wall1,TSnakeBuf:Wall2,TSnakeBuf:Wall3,TSnakeBuf:Wall4,TSnakeBuf:Wall5,TSnakeBuf:Wall6,TSnakeBuf:Wall7,TSnakeBuf:Wall8,TSnakeBuf:Wall9;TSnakeBuf:TBmpPos TSnakeBuf:BmpPos = / Wall Bean Super Head Horz Vert CrnUL CrnUR CrnDL CrnDR TailU TailD TailL TailR Stage 4,1,4,2,5,2,5,1,4,0,5,0,0,1,1,1,0,2,1,2,3,1,2,2,2,1,3,2,5,2, 0,0,1,0,3,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,3,0,;TSnakeBuf:TSnakeBuf() _Snake = 0; _iBeanNo = 0; _iStageBeans = 200; _iScore = 0; _bGameOver = false; _bEndStage = false; memset(_Units,0,sizeof(_Units); memset(_DispBuf,0,sizeof(_DispBuf);TSnakeBuf:TSnakeBuf() ClearSnake();void TSnakeBuf:ClearSnake(void) if(_Snake) TSnakeNode *toDel; _Snake-Prev-Next=0; while(_Snake) toDel=_Snake; _Snake=_Snake-Next; delete toDel; _Snake=0; void TSnakeBuf:InitSnake(void) ClearSnake(); _Snake = new TSnakeNode; TSnakeNode *nd = new TSnakeNode; _Snake-x = UnitX/2; _Snake-y = UnitY-2; _Snake-Next = nd; _Snake-Prev = nd; nd-x = UnitX/2; nd-y = UnitY-1; nd-Next = _Snake; nd-Prev = _Snake;void TSnakeBuf:StepMove(int d) if(_Snake)&(d)&(!_bGameOver)&(!_bEndStage) TSnakeNode NewPos = *_Snake; switch(d) case sdUp : NewPos.y-; break; /up case sdDown : NewPos.y+; break; /down case sdLeft : NewPos.x-; break; /left case sdRight: NewPos.x+; break; /right default : return; /do nothing if(NewPos.x0)|(NewPos.y=UnitX)|(NewPos.y=UnitY) _bGameOver = true; return; if(GetDispBuf(NewPos.x,NewPos.y)=sbnWall) _bGameOver = true; return; if(GetDispBuf(NewPos.x,NewPos.y)=sbnHead)&(GetDispBuf(NewPos.x,NewPos.y)x = NewPos.x; NewNode-y = NewPos.y; NewNode-Next = _Snake; NewNode-Prev = _Snake-Prev; _Snake-Prev-Next = NewNode; _Snake-Prev=NewNode; _Snake = NewNode; _iScore += ssEat; else _Snake = _Snake-Prev; _Snake-x = NewPos.x; _Snake-y = NewPos.y; DrawSnake(); if(bEat) if(!GenBean() _bEndStage = true; _iScore += ssStage; int TSnakeBuf:GetDispBuf(int x, int y) if(x=0) & (x=0) & (y=0) & (x=0) & (y=0) & (x=0) & (yNext; _DispBuf_Snake-y_Snake-x=sbnHead; while(lpNode)&(lpNode!=_Snake) if(lpNode-Next=_Snake) if(lpNode-y=lpNode-Prev-y) _DispBuflpNode-ylpNode-x = (lpNode-xPrev-x?sbnTailL:sbnTailR); else _DispBuflpNode-ylpNode-x = (lpNode-yPrev-y?sbnTailU:sbnTailD); else if(lpNode-y=lpNode-Prev-y) if(lpNode-ylpNode-Next-y) _DispBuflpNode-ylpNode-x=(lpNode-xPrev-x)?sbnCornDL:sbnCornDR; else if(lpNode-yNext-y) _DispBuflpNode-ylpNode-x=(lpNode-xPrev-x)?sbnCornUL:sbnCornUR; else _DispBuflpNode-ylpNode-x=sbnHorz; else if(lpNode-xNext-x) _DispBuflpNode-ylpNode-x=(lpNode-yPrev-y)?sbnCornUL:sbnCornDL; else if(lpNode-xlpNode-Next-x) _DispBuflpNode-ylpNode-x=(lpNode-yPrev-y)?sbnCornUR:sbnCornDR; else _DispBuflpNode-ylpNode-x=sbnVert; lpNode = lpNode-Next; void TSnakeBuf:InitStage(int StgNum) _iBeanNo = 0; _bGameOver = false; _bEndStage = false; memset(_Units,0,sizeof(_Units); memset(_DispBuf,0,sizeof(_DispBuf); GenWalls(StgNum); InitSnake(); DrawSnake(); GenBean();void TSnakeBuf:ClearScore(void) _iScore = 0;bool TSnakeBuf:GenBean(void) if(+_iBeanNo=0; i+) if(lpWalli.x1=lpWalli.x2) for(int y=lpWalli.y1; y=lpWalli.y2; y+) SetUnit(lpWalli.x1,y,sbnWall); else for(int x=lpWalli.x1; x0) iSkipUserEvent-; ResetEvent(hTimer);void _fastcall TSnakeTimer:Execute(void) Synchronize(SyOnStart); while(!Terminated) WaitForSingleObject(hTimer,dwWaitTime); if(!Terminated) Synchronize(SyOnTimer); Synchronize(SyOnExit);void _fastcall TSnakeTimer:fSetInterval(DWORD dwIntv) dwWaitTime = dwTimeToWait = dwIntv; iSkipUserEvent = 1; TriggerTimer();void _fastcall TSnakeTimer:TriggerTimer(int iWait) if(hTimer) if(iWait0) iSkipUserEvent = iWait+1; SetEvent(hTimer); 3.#include #pragma hdrstop#include UnitEnterName.h#pragma package(smart_init)#pragma resource *.dfmTFormEnterName *FormEnterName;_fastcall TFormEnterName:TFormEnterName(TComponent* Owner) : TForm(Owner) EditName-Clear();4.#include #pragma hdrstop#include UnitTest.h#include UnitAbout.h#include UnitEnterName.h#include #pragma package(smart_init)#pragma resource *.dfmTFormMain *FormMain;_fastcall TFormMain:TFormMain(TComponent* Owner) : TForm(Owner) randomize(); LoadParams(); StageNo = 0; Paused = false; DrMove = TSnakeBuf:sdUp; int dx = ScrollBoxSnake-Width - PaintBoxSnake-Width; int dy = ScrollBoxSnake-Height - PaintBoxSnake-Height; ScrollBoxSnake-Width = dx + TSnakeBuf:UnitX*16; ScrollBoxSnake-Height = dy + TSnakeBuf:UnitY*16; ScrollBoxSnake-DoubleBuffered = true; MiBlocks-Checked=SnakeParams.BmpSet; LabelHS-Caption=SnakeParams.HighScore; LabelStage-Caption=StageNo+1; LabelScore-Caption=SnakeBuf.Score; LabelHome-Font-Color = clBlue; LabelHomeDefProc = LabelHome-WindowProc; LabelHome-WindowProc = LabelHomeWndProc; RunBmp = new Graphics:TBitmap; RunBmp-LoadFromResourceName(0,BMP_SNAKE); RunBmp-PixelFormat = pfDevice; PausedBmp = new Graphics:TBitmap; PausedBmp-LoadFromResourceName(0,BMP_PAUSED); PausedBmp-PixelFormat = pfDevice; PausedBmp-Transparent = true; OverBmp = new Graphics:TBitmap; OverBmp-LoadFromResourceName(0,BMP_GMOVER); OverBmp-PixelFormat = pfDevice; OverBmp-Transparent = true; MaskBmp = new Graphics:TBitmap; MaskBmp-Assign(RunBmp); MaskBmp-Mask(MaskBmp-Canvas-PixelsMaskBmp-Width-1MaskBmp-Height-1); SnakeTimer = new TSnakeTimer; SnakeTimer-Interval = 300; SnakeTimer-OnTimer = SnakeTimerTimer;_fastcall TFormMain:TFormMain() SnakeTimer-DestroyTimer(); delete MaskBmp; delete OverBmp; delete PausedBmp; delete RunBmp;void _fastcall TFormMain:LabelHomeWndProc(Messages:TMessage &Message) if(Message.Msg=CM_MOUSEENTER) LabelHome-Font-Color = clRed; LabelHome-Font-Style = LabelHome-Font-StyleFont-Color = clBlue; LabelHome-Font-Style = LabelHome-Font-StylefsUnderline; LabelHomeDefProc(Message);void _fastcall TFormMain:LabelHomeClick(TObject *Sender) ShellExecute(Handle,open,/,0,SW_SHOWNORMAL);void _fastcall TFormMain:PaintBoxSnakePaint(TObject *Sender) TPaintBox *pb = (TPaintBox*)Sender; TCanvas *lpCanvas = pb-Canvas; TRect rc(pb-Left,pb-Top,pb-Left+pb-Width,pb-Top+pb-Height); lpCanvas-Brush-Style = bsSolid; lpCanvas-Brush-Color = clWhite; lpCanvas-FillRect(rc); int u, x0,y0,x1,y1; TSnakeBuf:TSnakeNode *lpPoint; for(int y=0; yTSnakeBuf:UnitY; y+) x1=0; y1=y*16; for(int x=0; x0) u-; x0=TSnakeBuf:BmpPosSnakeParams.BmpSet.Posu.x*16; y0=TSnakeBuf:BmpPosSnakeParams.BmpSet.Posu.y*16; :BitBlt(lpCanvas-Handle,x1,y1,16,16, RunBmp-Canvas-Handle,x0,y0, SRCINVERT); :BitBlt(lpCanvas-Handle,x1,y1,16,16, MaskBmp-Canvas-Handle,x0,y0, SRCAND ); :BitBlt(lpCanvas-Handle,x1,y1,16,16, RunBmp-Canvas-Handle,x0,y0, SRCINVERT); x1+=16; if(Paused) int w=PausedBmp-Width,h=PausedBmp-Height; int x=(pb-Width-w)/2,y=(pb-Height-h)/2; lpCanvas-Draw(x,y,PausedBmp); else if(SnakeBuf.GameOver) int w=OverBmp-Width,h=OverBmp-Height; int x=(pb-Width-w)/2,y=(pb-Height-h)/2; lpCanvas-Draw(x,y,OverBmp); void _fastcall TFormMain:SnakeTimerTimer(TObject *Sender) if(!SnakeBuf.GameOver)&(StageNoCaption=SnakeBuf.Score; PaintBoxSnake-Invalidate(); bCheckScore = true; /Application-MessageBox(Game Over!,Game Over,MB_OK|MB_ICONSTOP); if(SnakeBuf.EndStage) StageNo+; StageNo%=TSnakeBuf:StageCount; LabelScore-Caption=SnakeBuf.Score; /Application-MessageBox(Next stage.,Next stage,MB_OK|MB_ICONINFORMATION); LabelStage-Caption=StageNo+1; DrMove = TSnakeBuf:sdUp; SnakeBuf.InitStage(StageNo); LabelScore-Caption=SnakeBuf.Score; PaintBoxSnake-I

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论