[精选]vc可视化课程设计mfc贪吃蛇--资料_第1页
[精选]vc可视化课程设计mfc贪吃蛇--资料_第2页
[精选]vc可视化课程设计mfc贪吃蛇--资料_第3页
[精选]vc可视化课程设计mfc贪吃蛇--资料_第4页
[精选]vc可视化课程设计mfc贪吃蛇--资料_第5页
已阅读5页,还剩22页未读 继续免费阅读

下载本文档

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

文档简介

1、课程名称 可视化编程(VC) 学院计算机科学与技术学院 专业软件工程专业 班 级 姓 名 指导教师 2012 2013学年 第2学期 目录 1、 课程设计要求2 2、 系统功能实现与操作 2 3、系统设计概述 2 3.1添加结构体说明2 3.2模块说明3 3.3主要功能函数代码及注释 3 4、调试过程11 4.1添加功能说明11 4.2错误及解决方案11 5、程序运行结果12 附:主要类 Cview的成员函数代码 15 1、课程设计要求 题目: 基于MFC的贪吃蛇游戏设计与实现。 要求: 1. 游戏界面设计 2. 食物的初始化 3. 游戏开始以及具体实现 2、系统功能实现与操作 本系统运用AP

2、I函数的相关功能进行界面设计和功能实现。通过Rectangle ()函数绘制操作区域及障碍物。通过连续的小矩形实现蛇身的绘制。通过 srand0函数和 rand()函数生成随机数,完成生成食物功能的实现。综合运用多种if条件判断和 for循环的嵌套使用的算法完成各种条件判断。 该系统功能简单,操作简易。打开程序后,点击菜单栏的游戏按钮,点击 开始游戏,系统弹出对话框,提示还有3秒开始。游戏开始后,贪吃蛇开始移动, 通过操作键盘上的上下左右方向键控制蛇的移动,躲避障碍物并吃掉食物。当吃 掉的食物累计到达一定数量后,蛇行速度加快。直至撞到边界或障碍物或撞到自 身,游戏结束。此时弹出对话框,提示所得

3、分数。游戏中途可通过暂停和继续按 钮执行相应操作。 3、系统设计概述 3.1添加结构体说明 struct Sn ake int x,y; int len; int direct; S nake50; struct Food int x; int y; int food; Food; Snake结构体数组用于存放贪吃蛇的相关数据,其中 x,y存放当前节点矩 形左上角的坐标,(Snake0为蛇头),len存放当前蛇身的长度,direct存放蛇的 行进方向,可在14取值。 Food结构体用于存放食物的位置信息。其中 x, y存放食物小矩形左上角左 标,food存放食物存在的布尔判断值。 3.2模块说

4、明 系统代码部分主要分为三个模块,界面控制模块、初始化模块和功能模块。 界面控制模块包括函数:OnStart(),OnPause() OnContinue(),OnExit() 初始化模块包括函数:OnlnitialUpdate(),OnDraw(), oninit() 功能模块包括函数:OnKeyDown(),OnTimer() 3.3主要功能函数代码及注释 OnStart() void CSn akeView: On Start() / TODO: Add your comma nd han dler code here SetTimer(1,3000,NULL); AfxMessageB

5、ox(还有 3 秒开始 !); 点击开始游戏触发,设置定时器控制三秒后开始游戏。 OnPause() void CSn akeView:O nPause() / TODO: Add your comma nd han dler code here KillTimer(1); AfxMessageBox(不要让人家等太久); 关闭定时器,暂停游戏 OnContinue() void CSn akeView: OnContin ue() / TODO: Add your comma nd han dler code here SetTimer(1,10,NULL); 重启定时器,恢复游戏 OnEx

6、it() void CSn akeView:O nExit() / TODO: Add your comma nd han dler code here AfxMessageBox(欢迎下次再来!); exit(0); 弹出对话框提示退出。 OnlnitialUpdate() void CSn akeView: Onln itialUpdate() CView:O nln itialUpdate(); / TODO: Add your specialized code here an d/or call the base class Sn ake0.x=10; Sn ake0.y=10; Sn

7、 ake1.x=10; Sn ake1.y=10; Sn ake2.x=10; Sn ake2.y=10; Sn ake0.direct=2; Sn ake0.le n=3; Food.food=1;初始化蛇的长度和位置 用这个函数进行蛇的初始化工作。初始化贪吃蛇起初有3个节点,长度为3, 起始坐标存入数组,食物为1无0有。 OnDraw() void CSn akeView: On Draw(CDC* pDC) CSn akeDoc* pDoc = GetDocume nt(); ASSERT_VALID(pDoc); / TODO: add draw code for n ative da

8、ta here CBrush backBrush(RGB(111,111,111); CBrush* pOldBrush = pDC-SelectObject( CRect rect; pDC-GetClipBox( pDC-PatBlt(rect.left, rect.top, rect.Width(), rect.Height(),PATCOPY); pDC-SelectObject(pOldBrush); pDC-Recta ngle(9,9,401,401); CBrush zaBrush(RGB(111,111,111); pDC-SelectObject(zaBrush); for

9、(i nt m=0;mRecta ngle(150,(100+m*10),160,(110+m*10); for(i nt n=0 ;* 10; n+) pDC-Recta ngle(250+n*10),200,(260+n*10),210); onini t(); 窗口创建时架构调用的函数,通过此函数完成界面初始化。创建灰色画刷选 入设备环境,通过绘图函数绘制用户区。用两个 for循环逐次绘制矩形的算法绘 制出场景中的障碍物。 oninit() void CSn akeView:o nin it() CDC *pDC=GetDC(); CBrush DrawBrush=(RGB(255,0,

10、0); CBrush *Drawbrush=pDC-SelectObject( for(i nt i=0;iRecta ngle(S nakei.x*10,S nakei.y*10,(S nakei.x+1)*10,(S nakei.y+1) *10); pDC-SelectObject(DrawBrush); /利用 for循环绘制起始的蛇身 该函数为自己添加的成员函数,用于绘制开始时的蛇身(长度为3)。 OnKeyDown() void CSn akeView: On KeyDow n( UINT nChar, UINT nRepC nt, UINT n Flags) / TODO: Ad

11、d your message han dler code here an d/or call default switch( nChar) case VK_UP:if(S nake0.direct!=2) Sn ake0.direct=1;break; case VK_DOWN:if(S nake0.direct!=1) Sn ake0.direct=2;break; case VK_LEFT:if(S nake0.direct!=4) Sn ake0.direct=3;break; case VK_RIGHT:if(S nake0.direct!=3) Sn ake0.direct=4;br

12、eak; _ 通过键盘设置转头方向 CView:O nKeyDow n(n Char, nRepC nt,n Flags); CView:O nKeyDow n(n Char, nRepC nt,n Flags); 该函数为键盘消息的接收函数。从键盘得到的上下左右的不同按键,会根据 switch判断语句的case改变Snaka direct的值,从而改变蛇的行进方向。 OnTimer() void CSn akeView: On Timer(UINT nIDEve nt) / TODO: Add your message han dler code here an d/or call defa

13、ult CDC *pDC=GetDC(); CStri ng soure; int j=0; if(Sn ake0.le n=3)SetTimer(1,170,NULL); if(Sn ake0.le n=9)SetTimer(1,130,NULL); if(Sn ake0.le n=14)SetTimer(1,95,NULL); if(Sn ake0.le n=18)SetTimer(1,60,NULL); 根据蛇的长度进行速度的设定 soure.Format(得分:%d!,(S nake0.le n-3)*10); / 设置每个食物 100 分 撞墙判断 if(S nake0.direct

14、=3)用来控制直接结束当前函数 KillTimer(1); AfxMessageBox(soure); 分四种情况撞障碍判断,k为循环控制标识 if(Sn ake0.direct=3) for(i nt k=0;k20;k+) if(Sn ake0.x*10=160用来控制直接结束当前函数 KillTimer(l); AfxMessageBox(soure); if(Sn ake0.x*10=350用来控制直接结束当前函数 KillTimer(1); AfxMessageBox(soure); / if(Sn ake0.direct=2) for(i nt k=0;k10;k+) if(Sn

15、ake0.x*10=(250+k*10)用来控制直接结束当前函数 KillTimer(1); AfxMessageBox(soure); if(Sn ake0.x*10=150用来控制直接结束当前函数 KillTimer(1); AfxMessageBox(soure); / if(Sn ake0.direct=1) for(i nt k=0;k10;k+) if(Sn ake0.x*10=(250+k*10)用来控制直接结束当前函数 KillTimer(1); AfxMessageBox(soure); if(Sn ake0.x*10=150用来控制直接结束当前函数 KillTimer(1)

16、; AfxMessageBox(soure); / if(Sn ake0.direct=4) for(i nt k=0;k3) for(i nt sn=Sn ake0.le n-1;s n 0;s n-) if(Sn ake0.x*10=S nakes n.x*10 KillTimer(1); AfxMessageBox(soure); /对尾节点用白笔涂掉 if(j!=1) pDC-SelectStockObject(WHITE_PEN); pDC-Recta ngle(S nakeS nakeO.le n-1.x*10,S nakeS nakeO.le n-1.y*10,(S nak eS

17、 nake0.le n-1.x+1)*10,(S nakeS nake0.le n-1.y+1)*10); for(i nt i=S nake0.le n-1;i0;i-) Sn akei.x=S nakei-1.x; Sn akei.y=S nakei-1.y; 行走方向判断 if(Sn ake0.direct=1)S nake0.y-; if(Sn ake0.direct=2)S nake0.y+; if(Sn ake0.direct=3)S nake0.x-; if(Sn ake0.direct=4)S nake0.x+; pDC-SelectStockObject(BLACK_PEN)

18、; CBrush DrawBrush=(RGB(255,0,0); CBrush *Drawbrush=pDC-SelectObject( if(j!=1) pDC-Recta ngle(S nake0.x*10,S nake0.y*10,(S nake0.x+1)*10,(S nake0.y+1)*1 0); pDC-SelectObject(DrawBrush); 判断吃食物的条件 if(Sn ake0.x*10=Food.x*10 Food.food=1; Sn akeS nake0.le n-1.x=S nakeS nake0.le n-2.x; Sn akeS nake0.le n-

19、1.y=S nakeS nake0.le n-2.y; 生成食物 in t o=1;控制生成食物成功时跳出循环 if(Food.food=1) sran d( un sig ned)time(NULL); do Food.x=ra nd()%40; Food.y=ra nd()%40; if(Food.x!=0p20;p+) if(Food.x*10!=15 0 if(o!=1) for(i nt q=0;qRecta ngle(Food.x*10,Food.y*10,(Food.x+1)*10,(Food.y+1)*10); Food.food=0; CView:O nTimer( nIDE

20、ve nt); 主要功能函数,响应于定时器消息,用于实时改变游戏界面,是游戏功能实 现的主要函数。下面依次解释其中功能模块: 1、用四个if判断语句对蛇身长度进行判断,然后设置定时器间隔控制蛇行速度。 2、对撞墙进行判断,当蛇头的坐标企图越过系统边界并且其行进方向是冲着墙 的方向时,判定撞墙,关闭定时器并且置程序结束标志j=1 o 3、撞障碍物判断,同撞墙判断,对蛇的行进方向分上下左右四种情况进行判断, 然后判断蛇头坐标是否企图越过障碍物。若撞届则同样置程序结束标志j=1 o 4、撞蛇身判断,此算法是if嵌套for循环嵌套if判断,对蛇头的坐标和舍身每 一点的坐标进行一次比较,看是否有蛇头的坐

21、标与蛇身坐标重合。 若有则判定自 撞,置程序结束标志j=1 o 5、蛇行进的实现。蛇行进主要的算法是,每一次 Timer消息,将蛇的蛇头的下 一位置添加一个矩形,并且将蛇尾的小矩形用与背景相同颜色的矩形填充掉,完 成删除。通过一个for循环来实现。 6行走方向判断,通过对 Snake.direct进行判断,控制蛇头坐标在 x,y方向上 自加或自减,完成方向的设定。 7、判断吃食物的条件,若蛇头坐标与食物坐标重合,则吃食物。置食物标识为 1表示没有食物。 8、生成食物方法。通过rand()函数产生随机数,通过计算得到相应食物的坐标。 对该坐标的可行性进行判断,若坐标在操作区外或在障碍物中,则舍弃

22、,循环执 行这一步知道得到可行坐标,绘制食物矩形 4、调试过程 4.1添加功能说明 在此软件完成后,仅能实现定速度的无障碍的贪吃蛇游戏。经过改进,添加 了初始化的相应代码,修改了 Timer()函数的相关功能代码,实现了速度根据食 物个数可变,添加了障碍物。 4.2错误及解决方案 在编写程序的过程中遇到了诸多错误, 除书写错误外,其他错误通过探讨和 查阅资料的方式得到解决。具体问题有以下几个: 之前对MFC图形的相关类了解的比较少,仔细看书后学习了CDC类的相关 知识,了解了在NFC编程中图形函数的使用方法。 在遍写程序之前,不清楚在单文档 MFC程序中,架构对各个类的功能函数的 调用次序,所

23、以不知道应该将初始化的相关内容写在哪一个函数中,经查阅资料 得知,OnlnitialUpdate是视图窗口完全建立后第一个被框架调用的函数。框架在 第一次调用 On Draw前会调用Onln itialUpdate,因此Onln itialUpdate是设置滚动 视图的逻辑尺寸和映射模式的最合适的地方。在时间上,两者先后顺序不同,构 造函数生成本类的对象,但没有产生窗口,On Create后窗口产生,然后才是视图 的OnlnitialUpDate,般在这里对视图的显示做初始化。 在运行程序后,出现 BUG,当蛇行至靠近障碍物或墙壁那一列时就判定了撞 墙,导致蛇没有办法沿着游戏区域的边界行走,吃

24、不到边上的食物。仔细研究代 码后,在撞界判断中对蛇头坐标的基础上加入了对蛇行方向的判断,解决了这一 问题。 在撞界结束游戏后,蛇仍然会向前走一步,走到边界的外面。仔细研究代码后 没有发现错误,和同学探讨后发现,在OnTimer()函数中,撞界后则弹出对话框, 终止计时器,但程序还会将此函数执行完,所以蛇还会向前走一步。于是在撞界 判断中加入了程序结束标志,在撞界后立即结束程序不再执行任何语句。 解决了 这一问题。 在添加了障碍物之后食物生成在“墙”里。于是在生成随机数的判定中,加入 了对生成坐标在墙内的判断,解决了这一问题。 在程序完成后,我还想完成脱机运行的功能,即在没有VC的计算机上也能够

25、 运行这个程序。上网查阅了相关资料,了解到:在编写MFC程序时,对基类的 连接有静态和动态两种。当选择静态连接时,系统会在编译组建时将用到的类圭寸 装在程序中,就能够离开编程环境运行了。也就是MFC的EXE可执行文件分为 Debug版和Release版。于是这个问题也得到了解决。 最终,在不懈的努力下,程序终于得以完美运行了 5、程序运行结果 n , y 无历邀-sna 附:主要类Cview的成员函数代码 / sn akeView.cpp : impleme ntati on of the CSn akeView class / #i nclude stdafx.h #in clude sn

26、ake.h #in clude sn akeDoc.h #in clude sn akeView.h #ifdef _DEBUG #defi ne new DEBUG_NEW #un def THIS_FILE static char THIS_FILE = _FILE_; #en dif struct Sn ake int x,y; int len; int direct; Sn ake50; struct Food int兀 int y; int food; Food; / / CSn akeView IMPLEMENT_DYNCREATE(CS nakeView, CView) BEGI

27、N_MESSAGE_MAP(CS nakeView, CView) AFX_MSG_MAP(CS nakeView) ON_WM_KEYDOWN() ON_WM_TIMER() ON_COMMAND(ID_START, On Start) ON_COMMAND(ID_PAUSE, On Pause) ON_COMMAND(ID_EXIT, On Exit) ON_COMMAND(ID_CONTINUE, OnContin ue) AFX_MSG_MAP / Stan dard prin ti ng comma nds ON_COMMAND(ID_FILE_PRINT, CView:O nFil

28、ePri nt) ON_COMMAND(ID_FILE_PRINT_DIRECT, CView:O nF ilePri nt) ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView:O nFilePri ntPreview) END_MESSAGE_MAP() / / CSn akeView con structio n/destructio n CSn akeView:CS nakeView() / TODO: add con struct ion code here CSn akeView:CS nakeView() BOOL CSn akeView:PreCre

29、ateWi ndow(CREATESTRUCT / / CSn akeView draw ing void CSn akeView: On Draw(CDC* pDC) CSn akeDoc* pDoc = GetDocume nt(); ASSERT_VALID(pDoc); / TODO: add draw code for n ative data here CBrush backBrush(RGB(111,111,111); CBrush* pOldBrush = pDC-SelectObject( CRect rect; pDC-GetClipBox( pDC-PatBlt(rect

30、.left, rect.top, rect.Width(), rect.Height(),PATCOPY); pDC-SelectObject(pOldBrush); pDC-Recta ngle(9,9,401,401); CBrush zaBrush(RGB(111,111,111); pDC-SelectObject(zaBrush); /绘制障碍物 for(i nt m=0;mRecta ngle(150,(100+m*10),160,(110+m*10); for(i nt n=0 ;* 10; n+) pDC-Recta ngle(250+n*10),200,(260+n*10),

31、210); onin it(); / / CSn akeView printing BOOL CSn akeView:O nPreparePri nti ng(CPri ntlnfo* pI nfo) / default preparati on return DoPreparePri nti ng(pl nfo); void CSn akeView:O nBegi nPrintin g(CDC* /*pDC*/, CPrintlnfo* /*pI nfo*/) / TODO: add extra in itializati on before printing void CSn akeVie

32、w:O nEn dPri ntin g(CDC* /*pDC*/, CPrintlnfo* /*pI nfo*/) / TODO: add clea nup after printing / / CSn akeView diag no sties #ifdef _DEBUG void CSn akeView:AssertValid() const CView:AssertValid(); void CSn akeView:Dump(CDumpC on text CSn akeDoc* CSn akeView:GetDocume nt() / non-debug vers ion is inli

33、ne ASSERT(m_pDocume nt-lsKi ndOf(RUNTIME_CLASS(CS nakeDoc); return (CS nakeDoc*)m_pDocume nt; #endif /_DEBUG / / CSn akeView message han dlers void CSn akeView:O nKeyDow n(UINT n Char, UINT n RepC nt, UINT n Flags) / TODO: Add your message han dler code here an d/or call default switch( nChar) case

34、VK_UP:if(S nake0.direct!=2) Sn ake0.direct=1;break; case VK_DOWN:if(S nake0.direct!=1) Sn ake0.direct=2;break; case VK_LEFT:if(S nake0.direct!=4) Sn ake0.direct=3;break; case VK_RIGHT:if(S nake0.direct!=3) Sn ake0.direct=4;break; /通过键盘设置转头方向 CView:O nKeyDow n(n Char, nRepC nt, nF lags); CView:O nKey

35、Dow n(n Char, nRepC nt, nF lags); void CSn akeView:O nTimer(UINT nIDEve nt) / TODO: Add your message han dler code here an d/or call default CDC *pDC=GetDC(); CStri ng soure; int j=0; if(Sn ake0.le n=3)SetTimer(1,170,NULL); if(Sn ake0.le n=9)SetTimer(1,130,NULL); if(Sn ake0.le n=14)SetTimer(1,95,NUL

36、L); if(Sn ake0.le n=18)SetTimer(1,60,NULL); /根据蛇的长度进行速度的设定 soure.Format(”得分:d!,(Snake0.len-3)*10); / 设置每个食物 100 分 /撞墙判断 if(S nake0.direct=3)/用来控制直接结束当前函数 KillTimer(1); AfxMessageBox(soure); 分四种情况撞障碍判断,k为循环控制标识 if(Sn ake0.direct=3) for(int k=0;k20;k+) if(Sn ake0.x*10=160/用来控制直接结束当前函数 KillTimer(1); Af

37、xMessageBox(soure); if(Sn ake0.x*10=350/用来控制直接结束当前函数 KillTimer(1); AfxMessageBox(soure); / if(Sn ake0.direct=2) for(i nt k=0;k10;k+) if(Sn ake0.x*10=(250+k*10)用来控制直接结束当前函数 KillTimer(l); AfxMessageBox(soure); if(Sn ake0.x*10=150用来控制直接结束当前函数 KillTimer(1); AfxMessageBox(soure); / if(Sn ake0.direct=1) f

38、or(i nt k=0;k10;k+) if(Sn ake0.x*10=(250+k*10)用来控制直接结束当前函数 KillTimer(1); AfxMessageBox(soure); if(Sn ake0.x*10=150用来控制直接结束当前函数 KillTimer(1); AfxMessageBox(soure); / if(Sn ake0.direct=4) for(int k=0;k3) for(i nt sn=Sn ake0.le n-1;s n 0;s n-) if(Sn ake0.x*10=S nakes n.x*10 KillTimer(1); AfxMessageBox(

39、soure); /对尾节点用白笔涂掉 if(j!=1) pDC-SelectStockObject(WHITE_PEN); pDC-Recta ngle(S nakeS nake0.le n-1.x*10,S nakeS nake0.le n-1.y*10,(S nakeS nake0.l en-1.x+1)*10,(S nakeS nake0.le n-1.y+1)*10); for(i nt i=S nake0.le n-1;i0;i-) Sn akei.x=S nakei-1. x; Sn akei.y=S nakei-1.y; 行走方向判断 if(Sn ake0.direct=1)S

40、nake0.y-; if(Sn ake0.direct=2)S nake0.y+; if(Sn ake0.direct=3)S nakeO.x-; if(Sn ake0.direct=4)S nakeO.x+; pDC-SelectStockObject(BLACK_PEN); CBrush DrawBrush=(RGB(255,0,0); CBrush *Drawbrush=pDC-SelectObject ( if(j!=1) pDC-Recta ngle(S nake0.x*10,S nake0.y*10,(S nake0.x+1)*10,(S nake0.y+1)*10); pDC-SelectObject(DrawBrush); /判断吃食物的条件 if(Sn ake0.x*10=Food.x*10 Food

温馨提示

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

评论

0/150

提交评论