MFC应用开发技术
贪吃蛇游戏开发
学 院: 人民武装学院
专 业: 计算机工程与技术
班 级: 11 维护
学 号: 1120070257
学生姓名: 胡 桥 林
指导教师: 黄 顺 强
摘 要
本设计实现了一个简单的贪食蛇小游戏,该游戏不仅实现了简单的游戏操作功能,还实现了灵活的运作功能,而且具有简洁大方的图文外观。此设计按照软件工程的方法进行,系统具有良好的界面和必要的交互信息,使操作人员能快捷简单地进行操作,给玩家一个容易有趣的游戏。本系统开发平台为Windows XP,程序设计语言采用C++,在程序设计中,采用了结构化与面向对象两种解决问题的方法。
关键词:程序设计;计算器;MFC;按钮控件
目 录
第一章 游戏说明.................................. 4
1.1 功能描述............................................................. 4
1.2 VC++6.0 的介绍....................................................... 4
第二章 MFC的的概述............................... 5
2.1 MFC的介绍............................................................ 5
2.2 类的介绍............................................................. 5
第三章 总体设计说明.............................. 7
3.1 设计思路............................................................. 7
3.2 程序框图............................................................. 7
3.3 数据结构............................................................. 9
3.4 主要算法............................................................ 10
第四章 代码实现................................. 11
4.1 随机放置食物........................................................ 11
4.2 初始化数据.......................................................... 11
4.3 方向键控制蛇的运动方向.............................................. 13
第五章 运行结果................................. 17
5.1 初始界面............................................................ 17
5.2 开始游戏时的界面.................................................... 17
5.3 游戏运行时界面...................................................... 18
5.4 游戏结束............................................................ 18
总 结........................................... 20
致 谢........................................... 21
参考文献........................................ 22
第一章 游戏说明
贪食蛇是一个深受大众喜爱的简单游戏,玩家通过按键上的四个光标控制蛇的上下左右四个方向移动,蛇头碰撞到食物则表示食物被蛇吃掉,这时蛇的身长长一节,接着出现食物,等待被蛇吃掉,如果蛇在移动过程中,撞到墙壁或者身体交叉蛇头撞到自己的身体游戏结束
游戏运行环境:
设计环境:Microsoft Windows XP
开发工具:Visual C++ 6.0
运行环境:Microsoft Windows XP及以上版本
1.1 功能描述
游戏规则如下:
l 点击游戏->开始菜单游戏开始;
l 通过方向键控制蛇的运动方向,吃掉随机出现的豆子,若不小心碰到墙壁或者与自身相交,则该轮游戏结束;
l 点击 游戏->暂停按钮,暂停游戏;点击游戏->继续菜单,继续游戏;
l 点击设置->难度菜单,设定游戏难易程度;
l 点击游戏->结束菜单退出游戏。
l 单击帮助->游戏规则查看游戏规则。
1.2 VC++6.0 的介绍
VC++6.0 是 Microsoft 公司推出的一个基于 Windows 系统平台、可视化的 集成开发环境,它的源程序按 C++语言的要求编写,并加入了微软提供的功能 强大的 MFC(Microsoft Foundation Class)类库。MFC 中封装了大部分 Windows API 函数和 Windows 控件,它包含的功能涉及到整个 Windows 操作系统。MFC 不仅给用户提供了 Windows 图形环境下应用程序的框架, 而且还提供了创建应 用程序的组件,这样,开发人员不必从头设计创建和管理一个标准 Windows 应 用程序所需的程序,而是从一个比较高的起点编程,故节省了大量的时间。另 外,它提供了大量的代码,指导用户编程时实现某些技术和功能。因此,使用 VC++提供的高度可视化的应用程序开发工具和 MFC 类库, 可使应用程序开发变 得简单。
第二章 MFC的的概述
2.1 MFC的介绍
MFC(Microsoft Foundation Classes) , 是 一 个 微 软 公 司 提 供 的 类 库 ( class libraries) 以 C++类的形式封装了 Windows 的 API, , 它包含了窗口等许多类的定义。 各种类的集合构成了一个应运程序的框架结构,以减少应用程序开发人员的工作 量。其中包含的类包含大量 Windows 句柄封装类和很多 Windows 的内建控件和组 件的封装类。 MFC 6.0 版本封装了大约 200 个类,其中的一些可以被用户直接使用。例如 CWnd 类封装了窗口的功能,包括打印文本、绘制图形及跟踪鼠标指针的移动等; CsplitterWnd 类是从 CWnd 类派生出来的,继承了基类或称父类 CWnd 类的所有特 性,但增加了自己的功能,实现拆分窗口,使窗口至少可被拆分成两个窗口,用户 可以移动两个窗口之间的边框来改变窗口的大小;CtoolBar 类可以定义工具栏等。 MFC 命名的惯例是类的名字通常是由“C”打头;成员变量使用前缀“m_” , 接着使用一个字母来指明数据类型,然后是变量的名称;所有的单词用大写字母开头。
2.2 类的介绍
2.2.1 CWnd:窗口,它是大多数“看得见的东西”的父类(Windows里几乎所有看得见的东西都是一个窗口,大窗口里有许多小窗口),比如视图CView、框架窗口CFrameWnd、工具条CToolBar、对话框CDialog、按钮CButton,etc;一个例外是菜单(CMenu)不是从窗口派生的。该类很大,一开始也不必学,知道就行了。
2.2.2 CDocument文档,负责内存数据与磁盘的交互。最重要的是OnOpenDocument(读入),OnSaveDocument(写盘),Serialize(读写)。
2.2.3 CView视图,负责内存数据与用户的交互。包括数据的显示、用户操作的响应(如菜单的选取、鼠标的响应)。最重要的是OnDraw(重画窗口),通常用CWnd::Invalidate()来启动它。另外,它通过消息映射表处理菜单、工具条、快捷键和其他用户消息。你自己的许多功能都要加在里面,你打交道最多的就是它。
2.2.4 CDC设备文本。无论是显示器还是打印机,都是画图给用户看。这图就抽象为CDC。CDC与其他GDI(图形设备接口)一起,完成文字和图形、图像的显示工作。把CDC想象成一张纸,每个窗口都有一个CDC相联系,负责画窗口。CDC有个常用子类CClientDC(窗口客户区),画图通常通过CClientDC完成。
2.2.5 CDialog对话框。
2.2.6 CWinApp应用程序类。似于C中的main函数,是程序执行的入口和管理者,负责程序建立、消灭,主窗口和文档模板的建立。最常用函数InitInstance():初始化。
2.2.7 CGdiObject及子类,用于向设备文本画图。它们都需要在使用前选进DC。
2.2.8 CPen笔,画线。
2.2.9 CBrush刷子,填充。
2.2.10 CFont字体,控制文字输出的字体。
2.2.11 CBitmap位图。
2.2.12 CPalette调色板。
2.2.13 CRgn区域,指定一块区域可以用于做特殊处理
2.2.14 CFile文件。最重要的不外是Open(打开),Read(读入),Write( 写入)。
2.2.15 CString字符串。封装了C中的字符数组,非常实用。
2.2.16CPoint点,就是(x,y)对。
2.2.17 CRect矩形,就是(left,top,right,bottom)。
第三章 总体设计说明
3.1 设计思路
在数据结构上,用数组存储蛇以及蛇的运动区域。在数组中,每个元素有四个云感动方向,分别为RIGHT,LEFT,UP,DOWN.在没有蛇身的区域,数组的元素值为0。在蛇身的每个节点,用一个数组元素存储当前蛇节点的运动方向。通过改变数组中元素的值来表示蛇身的移动。在程序中运用定时器来保证蛇的持续移动。每个一定的时间间隔,蛇移动一格。在设计界面时。在Visual Studio 2008的环境下,建立基于对话框的工程,在工程下设计游戏界面,实现贪食蛇运行算法。在对话框中画出一个矩形,在大矩形中,用20x20的像素单位表示每一个蛇的节点。当数组节点的值不为0的时候,在大矩形中画出相应的蛇的节点矩形。并在蛇每移动一小格的时候,重绘整个窗口。在对蛇身进行绘画时。通过数组元素的值将蛇身在对话框的矩形中显示出来。在蛇身运动时,首先在蛇头位置蛇身增长一个节点,然后判断蛇头是否到达食物所在位置,若在食物所在位置,则蛇尾不减一,蛇身继续移动,若蛇头不再食物位置,则蛇尾减一,蛇身继续移动。若蛇头越界或者蛇头与蛇身重叠,则游戏结束。
3.2 程序框图
3.2.1 游戏控制模块框图
3.2.2函数成员
3.2.3“开始游戏”控制模块
moveSuccessful方法的流程图
3.3 数据结构
在程序中定义一个蛇的类,结构如下:
class Snake
{
public:
// bool gameStart;
void initData(); // 初始化蛇蛇的运动区域以及蛇身,蛇尾,//蛇头
void setFood(); // 随机产生食物的方法
bool move(const int &dir); // 蛇的移动方法
Snake(); // 构造函数
virtual Snake(); // 析构函数
public:
void game();
int m_SnakeMap[ROW][COL]; // 存储蛇的运动区域,用表示蛇身不再此区
// 域
bool m_gameStart; // 蛇开始运动标志
bool m_gameEnd; // 游戏结束
CPoint m_Tail; // 蛇尾位置
CPoint m_Head; // 蛇头位置
CPoint m_Food; // 食物位置
int m_Dir; // 蛇的运动方向
int m_Time; // 通过改变m_Time的值改变蛇的运动速度,
// 达到改变游戏难度的目的
};
另外程序中还有MFC自动生成的对话框类,不一一列出。
3.4 主要算法
void Snake::initData()初始化SnakeApp的数据,设置蛇运动的区域。设置蛇头,蛇尾,以及食物的位置。
bool Snake::move(const int &dir)蛇的运动算法,当蛇运动时,蛇头没有碰壁或和没有和蛇身重叠时,返回true,否则,放回false。当蛇头碰到食物时,蛇身增长一节。
void Snake::setFood()随机设置食物的位置,当食物与蛇头或蛇身重叠时,重新设置。
void CSnake1Dlg::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
通过键盘上的上下键控制蛇的运动方向。
void CSnake1Dlg::OnPaint()
当对话框的显示发生改变时,重绘窗口。
void CSnake1Dlg::OnTimer(UINT_PTR nIDEvent)
定时器,在设定的时间执行move()函数。
第四章 代码实现
4.1 随机放置食物
// 随机放置食物
void Snake::setFood()
{
srand(time(NULL));
m_Food.x = rand() % ROW;
m_Food.y = rand() % COL;
// 产生随机位置
while((m_SnakeMap[m_Food.y][m_Food.x]) || (m_Head == m_Food))
// 判断食物位置是否与蛇身重合
// 若重合则重新生成新的位置
{
m_Food.x = rand() % ROW;
m_Food.y = rand() % COL;
}
}
4.2 初始化数据
void Snake::initData()
{
m_gameStart = true; //游戏开始
m_gameEnd = false;
int i = 0;
int k = 0;
for( i = 0; i < ROW; i++)
{
for( k = 0; k <COL; k++)
{
m_SnakeMap[i][k] = 0;
// 初始化贪吃蛇运动区域
}
}
// 初始化贪吃蛇的运动方向
m_SnakeMap[0][0] = RIGHT;
m_SnakeMap[0][1] = RIGHT;
// 初始化蛇头位置
m_Head.x = 2;
m_Head.y = 0;
// 初始化蛇尾
m_Tail.x = 0;
m_Tail.y = 0;
// 随机放置食物
setFood();
// 初始化蛇的运动方向
m_Dir = RIGHT;
}
// 贪食蛇的移动函数
bool Snake::move(const int &dir)
{
switch(dir)
{
case RIGHT:
m_SnakeMap[m_Head.y][m_Head.x] = RIGHT;
m_Head.x++;
break;
case LEFT:
m_SnakeMap[m_Head.y][m_Head.x] = LEFT;
m_Head.x--;
break;
case UP:
m_SnakeMap[m_Head.y][m_Head.x] = UP;
m_Head.y--;
break;
case DOWN:
m_SnakeMap[m_Head.y][m_Head.x] = DOWN;
m_Head.y++;
break;
default:
break;
}
if(m_SnakeMap[m_Head.y][m_Head.x] || m_Head.x >= ROW || m_Head.x < 0 || m_Head.y < 0 || m_Head.y >= COL)
{
// 蛇头碰壁或者与蛇身重叠,死// 亡
m_gameEnd = true;
return false;
}
if(m_Head == m_Food)
{
// 吃到食物
m_Head = m_Food;
setFood();
return true;
}
else
{
int temp = m_SnakeMap[m_Tail.y][m_Tail.x];
m_SnakeMap[m_Tail.y][m_Tail.x] = 0;
switch(temp)
{
case LEFT:
m_Tail.x--;
break;
case RIGHT:
m_Tail.x++;
break;
case UP:
m_Tail.y--;
break;
case DOWN:
m_Tail.y++;
break;
default:
break;
}
return true;
}
}
4.3 方向键控制蛇的运动方向
// 方向键控制蛇的运动方向
void CSnake1Dlg::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
switch(nChar)
{
// 按↑键
case VK_UP:
if(SnakeApp.m_Dir == UP || SnakeApp.m_Dir == DOWN) return;
KillTimer(1);
//if(!SnakeApp.move(UP)) break;
SnakeApp.m_Dir = UP;
SetTimer(1, SnakeApp.m_Time, NULL);
break;
case VK_DOWN:
// 按↓键
if(SnakeApp.m_Dir == UP || SnakeApp.m_Dir == DOWN) return;
KillTimer(1);
//if(!SnakeApp.move(DOWN)) break;
SnakeApp.m_Dir = DOWN;
SetTimer(1, SnakeApp.m_Time, NULL);
break;
case VK_RIGHT:
// 按→键
if(SnakeApp.m_Dir == LEFT|| SnakeApp.m_Dir == RIGHT) return;
KillTimer(1);
//if(!SnakeApp.move(RIGHT)) break;
SnakeApp.m_Dir = RIGHT;
SetTimer(1, SnakeApp.m_Time, NULL);
break;
case VK_LEFT:
// 按←键
if(SnakeApp.m_Dir == LEFT|| SnakeApp.m_Dir == RIGHT) return;
KillTimer(1);
//if(!SnakeApp.move(LEFT)) break;
SnakeApp.m_Dir = LEFT;
SetTimer(1, SnakeApp.m_Time, NULL);
break;
default:break;
}
}
// 窗口重绘函数,收到WM_PAINT消息重绘窗口
void CSnake1Dlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
CClientDC dc(this);
// 画出蛇运动的矩形区域
dc.Rectangle(50,50,450,450);
// 三个不同颜色的画刷
CBrush brush(RGB(255,0,0));
CBrush brush1(RGB(0,255,0));
CBrush brush2(RGB(0,0,255));
CBrush brush3(RGB(0,255,255));
dc.FillRect(CRect(50,50,450,450),&brush3);
if(SnakeApp.m_gameStart)
{
if(SnakeApp.m_gameEnd)
{
// 游戏结束
MessageBox("很遗憾,游戏结束!!","GameOver",0);
return ;
}
if(SnakeApp.m_gameEnd == false)
{
CBrush *pOldBrush;
pOldBrush = dc.SelectObject(&m_Bsh[0]);
int xLeftTop, yLeftTop;
for (int i=0; i< ROW; ++i)
{
for (int j=0; j< COL; ++j)
{
if (SnakeApp.m_SnakeMap[i][j])
{
// 画出蛇身,绘为红色
xLeftTop = 51+j*20;
yLeftTop = 51+i*20;
dc.Rectangle(xLeftTop,yLeftTop,xLeftTop+19, yLeftTop+19);
dc.FillRect(CRect(xLeftTop,yLeftTop,xLeftop+19, yLeftTop+19),&brush);
}
}
}
// brush = brush(RGB(0,255,0));
// 画出蛇头,绘为绿色
xLeftTop = 51+SnakeApp.m_Head.x*20;
yLeftTop = 51+SnakeApp.m_Head.y*20;
dc.Rectangle(xLeftTop,yLeftTop,xLeftTop+19, yLeftTop+19);
dc.FillRect(CRect(xLeftTop,yLeftTop,xLeftTop+19, yLeftTop+19),&brush1);
// 画出食物,绘为蓝色
xLeftTop = 51+SnakeApp.m_Food.x*20;
yLeftTop = 51+SnakeApp.m_Food.y*20;
dc.Rectangle(xLeftTop,yLeftTop,xLeftTop+19, yLeftTop+19);
dc.FillRect(CRect(xLeftTop,yLeftTop,xLeftTop+19, yLeftTop+19),&brush2);
}
}
}
第五章 运行结果
5.1 初始界面
5.2 开始游戏时的界面
5.3 游戏运行时界面
5.4 游戏结束
总 结
本次能力扩展训练,我选择了通过运用MFC程序设计来编写一个贪食蛇的程序。在编写程序之前,我只有很少的关于MFC的程序设计知识,因此,在刚开始,我根本不知道从哪里下手开始解决我的问题。因此,首先我查阅许多关于贪食蛇的资料,也在网上看了许多关于贪食蛇的算法。做好了准备之后,才开始写我的贪食蛇。但是,在完成能力拓展训练的过程中还是遇到了许多问题。首先就是对于MFC不是很熟悉,在进行程序设计的过程中遇到了许多问题。首先我遇到的第一个问题是如何将存储贪食蛇节点的数组与显示相结合起来。在开始的两天,我一直没有能够解决这个问题,知道后来,我在网上查资料才找到一个比较好的解决方法。通过将数组的下标和对话框汇中点的坐标关联起来,从而绘制贪食蛇的节点。另一个问题是如何将菜单导入到对话框中,这个问题是通过请教MFC学的比较好的同学解决的。另外我还在程序设计的过程中碰到了如何让蛇身隔在每个给定的时间间隔内移动一个的问题,这也是通过和同学讨论解决的。以及这次能力拓展训练锻炼了我的动手能力。通过完成贪食蛇游戏的程序设计,增加了我的实际编程经验。提高了我独立解决问题的能力。
致 谢
经过这次设计,我的能力有了很大的提高,分析问题的能力、合作精神等方方面面都有了进步了。这期间凝结了很多人的心血,在此我表示由衷的感谢。没有他们的帮助,我将无法顺利完成这次设计。首先,我要特别感谢黄老师对我们的悉心指导,在设计期间黄老师帮助我们理清设计思路,指导设计方向和目标,并对我所做的课题提出宝贵的建议,老师渊博的知识,严谨的作风、诲人不倦的态度和学术上精益求精的精神让我受益终生。感谢各位老师在学习期间对我的严格要求。其次,游戏制作是一个看似简单,实则复杂的工作,这期间需要有耐心和毅力,所以还要感谢身边的老师和同学对我的毕业设计提供帮助和关心,让我认识到团队合作精神的力量和重要性,这将对我终生受益。
参考文献
[1]孙鑫.余安萍编著.VC++深入详解.北京.电子工业出版社.2007.11
[2]谭浩强.C++程序设计.北京.清华大学出版社.2004.06
[3]刘春辉.徐建飞编著.Visual C++程序设计学习笔记.北京.电子工业出版社.2008.05
[4]Charles Petzold著.Windows 程序设计(第五版).北京.北京大学出版社.1999.03
[5]任哲,《MFC Windows应用程序设计(第三版)》.清华大学出版社
MFC应用开发技术贪吃蛇游戏开发学院人民武装学院专业计算机工程与技术班级11维护学号1120xx0257学生姓名胡桥林指导教师黄顺…
贪吃蛇游戏C程序设计报告目录一设计要求2二设计的作用目的2三课题分析21贪吃蛇游戏功能分析22游戏界面分析33设计思路分析3四设计…
青岛理工大学琴岛学院设计报告课题名称贪吃蛇游戏设计学院青岛理工大学琴岛学院专业班级计算机网络技术091学号20xx03120xx7…
计算机实习报告姓名:班级:学号:小班序号:指导老师:题目:贪吃蛇(运行环境:visual,studio2010)邮箱:题目贪吃蛇实…
贪吃蛇JAVA设计报告第一章绪论1.1开发的背景随着科技的发展,现在手机的功能已不仅仅是简单的打接电话、收发短信了。更多的手机用户…
程序设计基础课程设计C课程设计报告贪吃蛇院系:计算机学院网络工程系班级:122班姓名:指导教师:20##年12月25日程序设计基础…
贪吃蛇游戏C程序设计报告目录一设计要求2二设计的作用目的2三课题分析21贪吃蛇游戏功能分析22游戏界面分析33设计思路分析3四设计…
贪吃蛇游戏C程序设计报告目录一设计要求2二设计的作用目的2三课题分析21贪吃蛇游戏功能分析22游戏界面分析33设计思路分析3四设计…
计算机实习报告姓名:班级:学号:小班序号:指导老师:题目:贪吃蛇(运行环境:visual,studio2010)邮箱:题目贪吃蛇实…
目录一软件设计要求和规范2二软件制作过程2三收获和体会13参考文献13一软件设计要求和规范11设计要求通过游戏程序设计提高编程兴趣…
电子与信息工程系开放性实验报告JAVA程序设计开放性实验报告专业班级学号姓名实验报告实验2贪吃蛇游戏设计4学时1实验内容1创建软件…