1、摘 要本设计实现了一个简单的贪食蛇小游戏,该游戏不仅实现了简单的游戏操作功能,还实现了灵活的运作功能,而且具有简洁大方的图文外观。此设计按照软件工程的方法进行,系统具有良好的界面和必要的交互信息,使操作人员能快捷简单地进行操作,给玩家一个简易有趣的游戏。本系统开发平台为Windows XP,程序设计语言采用C+,在程序设计中,采用了结构化与面向对象两种解决问题的方法。关键词:程序设计;计算器;MFC;按钮控件 20 / 20目 录引 言21. vc+6.0 简介 32 MFC 简介33.需求分析,系统功能 44.游戏要求55. 程序及系统结构设计66软件设计步骤77. 软件测试报告 15出现的
2、问题15结 论16参考文献16附 录19 引 言在程序设计中,通过设计、编制、调试一个模拟计算器的程序,加深对语法及语义分析原理的理解,并实现对命令语句的灵活应用。在程序设计中,可以用两种方法解决问题:一是传统的结构化程序设计方法,二是更先进的面向对象程序设计方法。由于多个函数均需要访问某些数据,这些数据常被设计为全局变量。而在面向对象程序设计中关键是如何将问题域中的实体(即日常所见的概念)抽取出来,作为C+程序中的类,而属性与行为作为类的两类要素通常是必不可少的,甚至还应考虑类必须满足的约束。本课程设计主要在运算过程中,如果通过计算器来完成,就会减少计算量,该程序即可以在简单计算器键面下进行
3、简单运算。1. vc+6.0 简介 VC+6.0 是 Microsoft 公司推出的一个基于 Windows 系统平台、可视化的 集成开发环境,它的源程序按 C+语言的要求编写,并加入了微软提供的功能 强大的 MFC(Microsoft Foundation Class)类库。MFC 中封装了大部分 Windows API 函数和 Windows 控件,它包含的功能涉及到整个 Windows 操作系统。MFC 不仅给用户提供了 Windows 图形环境下应用程序的框架, 而且还提供了创建应 用程序的组件,这样,开发人员不必从头设计创建和管理一个标准 Windows 应 用程序所需的程序,而是从
4、一个比较高的起点编程,故节省了大量的时间。另 外,它提供了大量的代码,指导用户编程时实现某些技术和功能。因此,使用 VC+提供的高度可视化的应用程序开发工具和 MFC 类库, 可使应用程序开发变 得简单。 2 MFC 简介 MFC(Microsoft Foundation Classes) , 是 一 个 微 软 公 司 提 供 的 类 库 ( class libraries) 以 C+类的形式封装了 Windows 的 API, , 它包含了窗口等许多类的定义。 各种类的集合构成了一个应运程序的框架结构,以减少应用程序开发人员的工作 量。其中包含的类包含大量 Windows 句柄封装类和很多
5、 Windows 的内建控件和组 件的封装类。 MFC 6.0 版本封装了大约 200 个类,其中的一些可以被用户直接使用。例如 CWnd 类封装了窗口的功能,包括打印文本、绘制图形及跟踪鼠标指针的移动等; CsplitterWnd 类是从 CWnd 类派生出来的,继承了基类或称父类 CWnd 类的所有特 性,但增加了自己的功能,实现拆分窗口,使窗口至少可被拆分成两个窗口,用户 可以移动两个窗口之间的边框来改变窗口的大小;CtoolBar 类可以定义工具栏等。 MFC 命名的惯例是类的名字通常是由“C”打头;成员变量使用前缀“m_” , 接着使用一个字母来指明数据类型,然后是变量的名称;所有的
6、单词用大写字母开 头。3.需求分析,系统功能贪吃蛇游戏需求分析贪吃蛇游戏作为一款经典小游戏,版本多样,娱乐性也很高,适合在闲暇时放松心神。并且可在多个平台上实现,程序简单易懂,非常适合MFC初学者学习制作。贪吃蛇游戏功能介绍一条蛇在密闭的围墙内,在围墙内随机出现一个食物,通过按键盘上的四个方向键控制蛇向上接着又出现食物,等待被蛇吃掉,如果蛇在移动过程中,撞到墙壁或身体交叉蛇头撞到自己的身体游戏结束。并且可以在游戏开始前自由选择游戏难度,游戏过程中可暂停游戏,并有积分系统,且积分每满一定值,蛇的运行速度会逐步增加。4.游戏要求(包括原始数据、技术参数、设计要求、图纸量、工作量要求等) l 采用面
7、向对象程序设计语言C+进行程序开发l 选用一种C+语言的开发环境设计界面及程序在C+6.0MFC开发环境下,进行程序的运行及调试5. 程序及系统结构设计贪吃蛇程序设计思路1、 方案讨论 贪吃蛇游戏作为一款经典的休闲类小游戏,深受同学喜爱,因此我们将贪吃蛇作为此次MFC课程设计题目。在最初的方案中,我们倾向于单文档(SDI)的形式设计,但最初尝试都因缺少一些文件等情况而失败。考虑到windows中自带小游戏大多采用对话框形式,为能更好的与同学们的使用习惯相一致,最终决定使用对话框(Dialogue)的形式。2、 数据结构在数据结构的选取,我们选择了链表,链表具有用多少空间就开多少空间的优点,使程
8、序执行更稳定,高效。游戏控制模块框开始游戏暂停游戏退出游戏继续游戏游戏控制模块函数成员 void InitTcs( )设置初始时蛇和果子的位置,及蛇头和一节蛇身的运动void MoveTcs ( )控制蛇的运动状态void AddTcs ( )蛇获得食物,长度增加void DrawTcs ( ) 确定以及画出蛇身,蛇头大小Void UnDrawTcs ( )蛇每向前运动一节需要重绘蛇及除去蛇的运动轨迹void DrawFood( )随机在指定区域出现果子int GameOver( )当蛇撞到墙壁或自己游戏结束InitTcs ()DrawTcs ()设置自动移动定时器和增加食物定时器游戏开始CT
9、csDlg:OnPaint()DrawFood ()桌面初始化初始化蛇头和蛇移动方向随机初始化一个食物到桌面SetTimer()CTable:AddFood()蛇移动蛇吃食?蛇增长继续?蛇死亡?桌面上随机生成食物MoveTcs ()AddTcs ()退出程序是是否否OnGameStart()GameOver()TB_STATE_SBLOCK贪吃蛇程序整体间调用关系6软件设计步骤:1)打开VC+6.0,选中MFCAppWizard(exe),选路径如图: 2)新建工程Tcs,在MFC的向导第一步选择单文档,按完成结束。如图3)打开Resourseview,在Menu中双击,如图:4)编好对话框后
10、,在类向导添加如下几个类:如图5)添加消息响应,在Project中选中Tcs,Class name选CTcs,在Object IDs和Messages分别作以下操作:如图6)在ClassWizard中为刚才编辑好的菜单添加消息处理函数。打开ClassWizard,选中Message Maps页。在Class Name中选择CTcsView,在Object ID中选择ID_GAME_ START,在Messages中选择COMMAND,添加消息处理函数。7)在ClassWizard中添加键盘消息处理函数。打开ClassWizard,选中Message Maps页。在Class Name中选择CT
11、csView,在Object ID中选择CTcsView,在Messages中选择WM_KeyDown,添加消息处理函数。8)在ClassWizard中定时器消息添加处理函数。打开ClassWizard,选中Message Maps页。在Class Name中选择CTcsView,在Object ID中选择CTcsView,在Messages中选择WM_Timer,添加消息处理函数。9)编辑生成的代码,完成程序。10)在程序定义宏定义,确定数值,构造函数,如图: 7. 软件测试报告 游戏编译程序:游戏初始界面:玩家可以在框内输入自己的名字,点击角色初始化,游戏便开始。游戏说明操作界面:当玩家输
12、入姓名后,点击开始,便弹出如下操作说明,玩家按Q键开始,空格键暂停,CTRL键调头,方向键表示方向。游戏运行界面:玩家可以在积分框那知晓自己的成绩,还可以在排分榜上看到自己名次。游戏结束界面:玩家失败,游记便结束,然后推出出现的问题 1、 问题:蛇运动区域与边框不匹配,造成蛇运动出边框或未到达边框而游戏结束。原因:相关数据不匹配。解决:重新对程序中的矩形框绘制函数数据进行修改,并修改蛇运动边界的判断条件。2、 问题:食物出现在边框外,造成游戏无法进行。原因:控制事物出现的随机函数出现问题,随机坐标超出蛇运动区域。解决:重新计算边界条件,修改随机函数rand()%x中的x值。3、 问题:记分牌有
13、时会出现记分错误。原因:尚不明确。参考文献:1)C+程序设计实践教程第2版 吴乃陵 李海文 高等教育出版社2)深入浅出MFC第2版 候俊杰 华中科技大学出版社3)Visual C+从入门到实践 葛亮 清华大学出版社 4) 郑莉,董渊,张瑞丰.C+语言程序设计.第3版.北京:清华大学出版.20035) 钱能.C+程序设计教程.第二版.北京:清华大学出版社.20056) 郑莉.C+语言程序设计案例教程.第一版.北京:清华大学出版社.20057) 韦朴,陈泰生. Visual C+通用范例开发金典.北京:电子工业出版社.20088) 揣锦华.面向对象程序设计与VC+实践.西安电子科技大学出版社,20
14、059) 张建宏,汤练兵,马德骏.计算机程序设计基础-C语言程序设计.科学出版社,200610) 陈清华.Visual C+课程设计案例精选与编程指导.东南大学出版社,2004 2012-06-25 附 录以下代码,我曾参考过,但有一个数组弄不清楚,此贴供大家参考:int m_nLeft, m_nTop, m_nWidth, m_nHeight, m_nSize; / 起始坐标,宽/高度(格数),每格大小int m_nDirect; / 当前方向/ 1-右,2-左,3-下,4-上CPoint m_pAim; / 当前目标坐标CArray m_aBody; / 蛇身int m_nGameStat
15、us; / 游戏状态:0-未开始,1-开始int m_nCount; / 吃掉目标数int m_nTime, m_nTime1; / 用时间;(2)在CSnakeView. Cpp文件,添加3个成员函数IniAim、IniGame和ReDiaplay:/ 该函数随机产生一个供蛇吃的目标,如果该目标恰巧与蛇身重合,则重新产生一个void CSnakeView:IniAim()int uX, uY; / 目标位置while (1)uX=rand ( ) % m_nHeight;uY=rand ( ) % m_nWidth;int uTag = 0; / 0-不与蛇身重合,1-重合for (int
16、i=0;i SelectStockObject (WHITE_BRUSH);pDC - Rectangle (CRect (m_nLeft - 1, m_nTop - 1, m_nLeft + m_nWidth * m_nSize + 1,m_nTop + m_nHeight * m_nSize + 1) ); / 显示当前用时CString uStr;uStr. Format (当前用时:% d, m_nTime);pDC - TextOut (m_nLeft + m_nWidth * m_nSize + 30, 40, uStr); / 显示当前得分uStr. Format (当前得分:
17、% d, m_nCount);pDC - TextOut (m_nLeft + m_nWidth * m_nSize + 30, 140, uStr); / 显示目标pDC - SelectStockObject (LTGRAY_BRUSH);pDC - Rectangle (CRect (m_nLeft + m_pAim. y * m_nSize, m_nTop + m_pAim. x * m_nSize,m_nLeft + (m_pAim. y + 1) * m_nSize, m_nTop + (m_pAim. x + 1 ) *m_nSize ); / 画蛇for (int i=0; i
18、 Rectangle (CRect (m_nLeft + uPoint. y * m_nSize, m_nTop + uPoint. x * m_nSize,m_nLeft + (uPoint. y + 1) * m_nSize, m_nTop + (uPoint. x + 1) * m_nSize) );(5)为游戏菜单下的开始项的消息映射函数添加代码。void CSnakeView:OnGameStart() / 启动游戏,启动定时器IniGame ( );m_nGameStatus = 1;SetTimer (1, 100, NULL);Invalidate ( );(6)为键盘按键消息
19、处理函数添加代码。/ 根据按下的方向键设置代表不同方向的值void CSnakeView:OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) switch (nChar)case 38:m_nDirect = 4;break;case 40:m_nDirect = 3;break;case 37:m_nDirect = 2;break;case 39:m_nDirect = 1;break; CView:OnKeyDown(nChar, nRepCnt, nFlags);(7)为定时器消息处理函数添加代码。void CSnakeView:OnTim
20、er(UINT nIDEvent) m_nTime1+; / 计时 if (m_nTime1 = 10) / 达到1秒m_nTime+;m_nTime1 = 0;Invalidate ( );CPoint uPoint = m_aBody. GetAt (0); / 蛇头的位置int uTag = 0; /是否失败 switch (m_nDirect) / 判断下一步蛇是否出界case 1: / rightuPoint. y+;if (uPoint. y = m_nWidth)uTag = 1;break;case 2: / leftuPoint. y-;if (uPoint. y = m_n
21、Height)uTag = 1;break;case 4: / upuPoint. x-;if (uPoint. x 0)uTag = 1;break;if (uTag =0) / 判断蛇是否碰到了自身for (int i=0; i = m_aBody.GetUpperBound(); i+)CPoint uPoint1 = m_aBody. GetAt (i);if (uPoint1. x = uPoint. x & uPoint1.y = uPoint. y)uTag = 1;break;if (uTag = 0)m_aBody. InsertAt (0, uPoint); / 新的蛇头的
22、位置ReDisplay (uPoint);if (uPoint. x = m_pAim. x & uPoint. y = m_pAim. y) / 碰上目标m_nCount+;IniAim ( );Invalidate ( );elseCPoint uPoint1 = m_aBody. GetAt (m_aBody.GetUpperBound ( ) );m_aBody. RemoveAt (m_aBody.GetUpperBound ( ) );ReDisplay (uPoint1);else / 游戏结束KillTimer(1);AfxMessageBox(Fail!);CView:OnTimer(nIDEvent); .忽略此处.