C++贪吃蛇课程设计.docx

上传人:b****6 文档编号:5151325 上传时间:2022-12-13 格式:DOCX 页数:18 大小:122.28KB
下载 相关 举报
C++贪吃蛇课程设计.docx_第1页
第1页 / 共18页
C++贪吃蛇课程设计.docx_第2页
第2页 / 共18页
C++贪吃蛇课程设计.docx_第3页
第3页 / 共18页
C++贪吃蛇课程设计.docx_第4页
第4页 / 共18页
C++贪吃蛇课程设计.docx_第5页
第5页 / 共18页
点击查看更多>>
下载资源
资源描述

C++贪吃蛇课程设计.docx

《C++贪吃蛇课程设计.docx》由会员分享,可在线阅读,更多相关《C++贪吃蛇课程设计.docx(18页珍藏版)》请在冰豆网上搜索。

C++贪吃蛇课程设计.docx

C++贪吃蛇课程设计

青岛理工大学琴岛学院

设计报告

 

课题名称:

基于C++贪吃蛇的设计与实现

学院:

计算机工程系

专业班级:

计算机科学与技术(专升本)

13级1班

学号:

XX

学生:

X

指导教师:

XX

 

青岛理工大学琴岛学院教务处

2013年12月27日

学生

邵坤

指导教师

XX

课题名称

基于C++贪吃蛇的设计与实现

设计时间

XXX

设计地点

8教209室

设计目的

动手练习制作MFC小应用。

锻炼自己动手制作、查询资料、独立思考的能力

指导教师评语

 

系部教研室

意见

 

一、需求分析

贪吃蛇游戏作为一款经典小游戏,版本多样,娱乐性也很高,适合在闲暇时放松心神。

并且可在多个平台上实现,程序简单易懂,非常适合初学者学习制作。

1、语言的使用

现在的贪吃蛇游戏一般是用C语言实现的,用C语言编写贪吃蛇游戏比较简单易懂,当然也可以用其他语言来实现,比如Java、C++、C#等,这里我们用C++来实现。

2、用C++的优势

C++在一定程度上可以和C语言很好的结合,甚至大多数C语言程序是在C++的集成开发环境中完成的。

C++相对众多的面向对象的语言,具有相当高的性能。

C++引入了面向对象的概念,使得开发人机交互类型的应用程序更为简单、快捷。

很多优秀的程序框架包括Boost、Qt、MFC、OWL、WTL就是使用的C++。

人们一般认为,使用Java或C#的开发成本比C++低。

但是,如果充分分析C++和这些语言的差别,会发现这句话的成立是有条件的。

这个条件就是:

软件规模和复杂度都比较小。

如果不超过3万行有效代码(不包括生成器产生的代码),这句话基本上还能成立。

否则,随着代码量和复杂度的增加,C++的优势将会越来越明显。

造成这种差别的就是C++的软件工程性。

相对于其他的语言,C++具有它自己的优势,主要体现在以下几个方面:

(1)、C++实现了面向对象程序设计。

在高级语言当中,处理运行速度是最快的,大部分的游戏软件,系统都是由C++来编写的。

(2)、C++语言非常灵活,功能非常强大。

如果说C语言的优点是指针,那么C++的优点就是性能和类层次结构的设计。

(3)、C++非常严谨、精确和数理化,标准定义很细致。

(4)、C++语言的语法思路层次分明、相呼应;语法结构是显式的、明确的。

当然,这只是C++的一部分优势,在运用过程中,我们会逐渐发现C++语言之美。

3、实现的功能

⑴运行程序。

⑵点击“游戏->开始”,出现围墙界面,一条蛇在密闭的围墙内,在围墙内随机出现一食物,游戏开始。

⑶游戏开始后,通过四个方向键控制蛇的运动方向,吃掉随机出现的豆子,若不小心碰到墙壁或者与自身相交,则该轮游戏结束。

⑷游戏结束后,会弹出游戏得分。

⑸点击“游戏->暂停”,暂停游戏。

⑹点击“游戏->继续”,继续游戏。

⑺游戏会根据蛇身的长度自动调节难易程度。

⑻点击“游戏->退出”,退出游戏。

⑼单击帮助->游戏规则查看游戏规则。

4、主要的思想

1定义蛇和食物的全局变量,初始化贪吃蛇各项成员变量,包括图像的出现在屏幕的初始位置,长度,以及蛇的行走方向。

食物类的定义包括出现的初始位置,以及食物是否被吃掉的判断。

2用数组初始化长度为3的贪吃蛇,并且默认食物未出现

3在CView类上运用MFC提供的Windows消息中WM_TIMER消息,运用OnTimer()函数让系统提供一个时钟节拍,更新游戏

4具体游戏实现,包括蛇撞到自己和围墙都将使游戏结束,判断吃豆等,其中还包括根据蛇的长度来进行游戏难度的改变。

5具体键盘游戏操作运用到Windows消息响应中的WM_KEYDOWN,用OnKeyDown()来响应玩家的实际操作

4、游戏界面如下:

 

 

图1游戏界面

 

图1

二、概要设计

1、首先,用一个结构体数组来标记蛇的X位置和Y位置,还有每一节的方向。

用一变量标识蛇的长度。

2、在蛇非转弯的移动时用定时器来自动移动,不管蛇是哪种形状,都只需在每次移动时先将各节向后移动(蛇尾舍弃,新的蛇尾由蛇尾的上一节代替):

如蛇本身为snake[0]到snake[3],就是将snake[0]到snake[2]一起移动到snake[1]到snake[3]:

将snake[2]的XY坐标赋值snake[3]的XY坐标,snake[1]的XY坐标赋值给snake[2]的XY坐标,snake[0]的XY坐标赋值给snake[1]的XY坐标。

再判断蛇头的方向,然后将蛇头顺着这个方向向前移动一格就是蛇头snake[0]的XY坐标。

而蛇除蛇头外各节的方向由函数SetDirection()来确定(明显此种情况,蛇头的方向不变),SetDirection()的思想是根据蛇的每一节的前一节的相对位置来确定本节的方向。

(其实这个函数是多余的,真正用到的只有蛇头的方向)。

3、蛇在转弯时,也是各节一次向后移,蛇头的位置顺着转弯的方向移动,方向由转弯方向确定。

4、蛇在吃到食物时,长度加一,蛇头的位置变成食物的位置,方向不变。

蛇的本身每节的XY位置都向后移。

如蛇本身为snake[0]到snake[3],就是将snake[0]到snake[3]一起移动到snake[1]到snake[4]。

5、具体键盘游戏操作运用到Windows消息响应中的WM_KEYDOWN,用OnKeyDown()来响应玩家的实际操作。

6、每次蛇在转弯时只能有一种方向按键能响应,即要么左右转,要么上下转。

蛇头方向向左或向右时,只能上下转;蛇头方向向上或向下时,只能左右转。

7、食物的位置由rand函数随机产生。

游戏运行界面如图2所示:

图2游戏界面

8、游戏框架如下:

 

 

图3游戏框架

3、主要类及成员函数、数据成员的说明如表1所示

表1

类的名称

成员名称

功能

Snake

x

蛇的横坐标

y

蛇的纵坐标

len

蛇的长度

direct

指引蛇的方向

Food

x

食物的横坐标

y

食物的纵坐标

sfood

食物个数

CSnakeView

OnStart()

控制游戏开始

OnPause()

控制游戏暂停

OnContinue()

控制游戏继续

OnExit()

控制游戏退出

OnKeyDown()

接收用户键入的信息,然后用switch进行选择判断

OnRButtonDown()

用鼠标右键屏幕,就会马上显示当前位置的坐标信息

OnRButtonDown()

该函数画一个矩形,用当前的画笔画矩形轮廓,用当前画刷进行填充

oninit()

该函数画一个矩形,用当前的画笔画矩形轮廓,用当前画刷进行填充

OnTime()

改变蛇的移动速度,判断蛇是否撞墙,食物的随机分配,吃食物以后长度的增加,蛇的移动方向的改变

OnDraw(CDC*pDC)

 用画刷画一个背景,并且包含当前可见区域的最小矩形的大小,使用当前选入指定设备环境中的刷子绘制给定的矩形区域

三、详细设计

1、添加消息处理函数

在已有工程下的ClassView中右键Cview类添加以下Windows信息

WM_RBUTTONDOWN

WM_RBUTTONDOWN

WM_TIMER

再右键CView类选择“ADDVirtualFunciton”选OnInitialUpdate()

OnInitialUpdate()的功能如下:

视图窗口完全建立后第一个被框架调用的函数。

框架在第一次调用OnDraw前会调用OnInitialUpdate,因此OnInitialUpdate是设置滚动视图的逻辑尺寸和映射模式的最合适的地方。

时间上,两者先后顺序不同,构造函数生成本类的对象,但没有产生窗口,OnCreate后窗口产生,然后才是视图的OnInitialUpDate,一般在这里对视图的显示做初始化。

简单点,就是ONCREATE只是产生VIEW的基本结构和变量而在OnInitialUpDate()中,主要初始化视图中控件等。

所以我们要用这个函数来进行贪吃蛇的初始化工作。

再者还要添加一个成员函数oninit()进行贪吃蛇外观的初始化。

2、控件的设计

再者是设计游戏的一些控件来控制“游戏开始”“游戏结束”和“游戏暂停”。

我们可以点击“工作空间”的“ResourceView”进行控件的具体设计,这里我们在Menu文件夹中把“IDR_MAINFRAME”中默认的控件全部删除,右键其中的标题栏,点击属性,会得到一个菜单栏标题,我们分别建立1个菜单栏标题。

这里我们分别建“游戏”。

图4添加的控件

点击并且在已有控件中的列表中点击属性,进行“菜单项目属性”的设置。

我们本别建立的属性“标明”与对应的ID有

游戏开始IDM_START

游戏暂停IDM_PAUSE

游戏继续IDM_CONTINUE

游戏退出IDM_EXIT

成功设置ID之后我们分别右键各项属性进行消息响应处理函数的生成

具体方法操作例子如下

1右键“游戏开始”

2点击“类向导建立”

3在MessageMaps页面,在要进行消息响应的控件ID列表ObjectIDs中上选择对应的ID,这里我们选择IDM_START,具体实现的环境是CView类,所以我们必须把“Classname”的默认“CMainFrame”改为“CView类”,并且在“Messages”类型设置中,用“COMMAND”设置为其为命令消息。

其余各项也按照同理进行设置。

3、具体实现游戏

Step1

首先我们在文件开头处分别定义蛇和食物的全局变量

staticstructSnake

{

intx,y;

intlen;

intdirect;

}Snake[1000];

staticstructFood

{

intx;

inty;

intisfood;

}Food;

再者初始化贪吃蛇

voidCSnakeView:

:

OnInitialUpdate()

{

CView:

:

OnInitialUpdate();

Snake[0].x=10;

Snake[0].y=10;

Snake[1].x=11;

Snake[1].y=10;

Snake[2].x=12;

Snake[2].y=10;

Snake[0].direct=3;

Snake[0].len=3;

Food.isfood=1;

}

初始化贪吃蛇起初有3个节点,长度为3和起始坐标;食物默认为1无0有。

Step2对OnKeyDown()具体添加代码

voidCSnakeView:

:

OnKeyDown(UINTnChar,UINTnRepCnt,UINTnFlags)

{

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);

}

代码说明:

Snake[0]代表的是蛇头,我们对蛇头的方向Snake[0].direct进行判断。

caseVK_UP:

if(Snake[0].direct!

=2)Snake[0].direct=1;break;意思就是当Snake[0].direct的方向此时并不等于“下”的时候,才能做出“上”的操作动作,否则则忽略用户“向上”的操作按键效果。

OnKeyDown函数的第一个参数UINTnChar是接收用户键入的信息,然后我们用switch进行选择判断。

Step3对OnRButtonDown()具体添加代码

voidCSnakeView:

:

OnRButtonDown(UINTnFlags,CPointpoint)

{

CStringstr;

str.Format("%d,%d",point.x,point.y);

AfxMessageBox(str);

CView:

:

OnRButtonDown(nFlags,point);

}

这个函数功能是:

用鼠标右键屏幕,就会马上显示当前位置的坐标信息。

Step4

voidCSnakeView:

:

oninit()

{

CDC*pDC=GetDC();

CBrushDrawBrush=(RGB(100,100,100));

CBrush*Drawbrush=pDC->SelectObject(&DrawBrush);

for(inti=0;i<=Snake[0].len-1;i++)

pDC->Rectangle(Snake[i].x*20,Snake[i].y*20,(Snake[i].x+1)*20,(Snake[i].y+1)*20);

pDC->SelectObject(DrawBrush);

}

代码说明:

利用Windows给我们提供的CDC类来进行画图,我们首先用一个指向CDC类的指针去接受与该窗口相关联的DC句柄,然后用定义画刷一个DrawBrush对象,并且用RGB(100,100,100)来给画刷初始化颜色。

并且用SelectObject(&DrawBrush);函数把对象画刷选入到设备描述表中,用for循环依次把贪吃蛇的3个节点画出来。

Step5控件添加代码

voidCSnakeView:

:

OnStart()

{

SetTimer(1,1000,NULL);

OnInitialUpdate();

}

voidCSnakeView:

:

OnPause()

{

KillTimer

(1);

AfxMessageBox("暂停游戏...");

}

voidCSnakeView:

:

OnExit()

{

AfxMessageBox("退出游戏...");

exit(0);

}

voidCSnakeView:

:

OnContinue()

{

SetTimer(1,10,NULL);

}

代码说明:

由于之前我们设定了WM_TIMER消息,我们能运用计时器功能。

用WM_TIMER来设置定时器

先请看SetTimer这个API函数的原型

  UINT_PTRSetTimer(

  HWNDhWnd,//窗口句柄

  UINT_PTRnIDEvent,//定时器ID,多个定时器时,可以通过该ID判断是哪个定时器

  UINTuElapse,//时间间隔,单位为毫秒

  TIMERPROClpTimerFunc//回调函数

  );

SetTimer(m_hWnd,1,1000,NULL);//一个1秒触发一次的定时器

在MFC程序中SetTimer被封装在CWnd类中,调用就不用指定窗口句柄了,所以我们这里可以只去后3个参数写成SetTimer(1,10,NULL);,1000为1秒。

Step6对OnDraw()的添加代码

voidCSnakeView:

:

OnDraw(CDC*pDC)

{

CSnakeDoc*pDoc=GetDocument();

ASSERT_VALID(pDoc);

CBrushbackBrush(RGB(100,0,100));

CBrush*pOldBrush=pDC->SelectObject(&backBrush);

CRectrect;

pDC->GetClipBox(&rect);

pDC->PatBlt(rect.left,rect.top,rect.Width(),rect.Height(),PATCOPY);

pDC->SelectObject(pOldBrush);

pDC->Rectangle(19,19,501,501);

oninit();

}

代码说明:

此处是用画刷画一个背景,并且画出3个矩形区域

函数原型:

intGetClipBox(HDChdc,LPRECTlprc);

该函数得到一个能够完包含当前可见区域的最小矩形的大小。

函数原型:

intnYLeft,intnWidth,intnHeight,DWORDdwRop); 

该函数使用当前选入指定设备环境中的刷子绘制给定的矩形区域。

Step7对OnTime()的添加代码

由于该函数代码部分太复杂我们将其分开逐一分析:

voidCSnakeView:

:

OnTimer(UINTnIDEvent)

{

CDC*pDC=GetDC();

CStringsoure;

SetTimer(1,360-Snake[0].len*10,NULL);

soure.Format("得分:

%d!

",(Snake[0].len-3)*10);

if(Snake[0].x*20<=37||Snake[0].y*20<=37||Snake[0].x*20>=462||Snake[0].y*20>=462)

{

KillTimer

(1);

AfxMessageBox(soure);

}

}

代码说明:

这一部分是蛇身撞界判断。

蛇的一节身体为一个矩形块,这样表示每个矩形块只需起点坐标x和y身体是不断增长的,所以用数组存放每一节的坐标。

voidCSnakeView:

:

OnTimer(UINTnIDEvent)

{if(Snake[0].len>3)

for(intsn=Snake[0].len-1;sn>0;sn--)

{

if(Snake[0].x*20==Snake[sn].x*20&&Snake[0].y*20==Snake[sn].y*20)

{

KillTimer

(1);

AfxMessageBox(soure);}

}

}

代码说明:

这一部分是蛇身相撞判断。

由于判断蛇自己是否咬到了自己,根据蛇长sn,进行sn次forsn-1次循环,并且和Snake[0].x进行比较(之所以进行sn-1次那肯定是不包括蛇头而且蛇的长度也必须大于3才会发生自己咬自己的情况)。

KillTimer

(1);是停止计时器;和之前的SetTime()对应而已。

AfxMessageBox(soure);输出一个原样输出内容。

voidCSnakeView:

:

OnTimer(UINTnIDEvent)

{if(Food.x==Snake[Snake[0].len-1].x&&Food.y==Snake[Snake[0].len-1].y)

{

}

else

{

pDC->SelectStockObject(WHITE_PEN);

pDC->Rectanglake[Snake[0].len-1].x*20,Snake[Snake[0].len-1].y*20,(Snake

[Snake[0].len-1].x+1)*20,(Snake[Snake[0].len-1].y+1)*20);

}

for(inti=Snake[0].len-1;i>0;i--)

{

Snake[i].x=Snake[i-1].x;

Snake[i].y=Snake[i-1].y;

}

}

代码说明:

pDC->SelectStockObject(WHITE_PEN);是把白色的“PEN”选入设备进行画图

pDC->Rectangle(Snake[Snake[0].len-1].x*20,Snake[Snake[0].len-1].y*20,

(Snake[Snake[0].len-1].x+1)*20,(Snake[Snake[0].len-1].y+1)*20);让它去画最后一个节点

for(inti=Snake[0].len-1;i>0;i--)//贪吃蛇的蛇身移动

{

Snake[i].x=Snake[i-1].x;

Snake[i].y=Snake[i-1].y;

}

这里要要专门用白笔画最后一个,因为我们的游戏界面是用白色的,贪吃蛇移动的时候,肯定是蛇头向前走一单位,而尾部肯定要“擦除”掉一个单位,那怎么擦除呢?

我们只能用和背景色一样的画笔。

原来蛇的位置和新蛇的位置差一个单位,所以看起来蛇会多一节身体,所以将蛇的最后一节用背景色覆盖SelectStockObject(WHITE_PEN)让它起到“消失”最后一个节点的功能,让我们以为蛇是向前走了。

Snake[i].x=Snake[i-1].x;

Snake[i].y=Snake[i-1].y;进行次数为"长度-1"次的循环

为什么要进行长度-1次呢?

我这里要说明一下,这里是不包括蛇头的进行的平移,用数组赋值的方法,把前一节点保存在后一个结点,然后头结点向前移动。

voidCSnakeView:

:

OnTimer(UINTnIDEvent)

{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++;

pDC->SelectStockObject(BLACK_PEN);

CBrushDrawBrush=(RGB(100,100,100));

CBrush*Drawbrush=pDC->SelectObject(&DrawBrush);

pDC->Rectangle(Snake[0].x*20,Snake[0].y*20,(Snake[0].x+1)*20,(Snake[0].y+1)*

20);

pDC->SelectObject(DrawBrush);

}

代码说明:

这一部分是方向判断。

“1234”本别代表“上下左右”x++,y++进行移动,然后用选定画刷画出一个新节点的矩形作为头结点

voidCSnakeView:

:

OnTimer(UINTnIDEvent)

{if(Snake[0].x*20==Food.x*20&&Snake[0].y*20==Food.y*20)

{

Snake[0].len++;

Food.isfood=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;

}

}

代码说明:

这一部分是判断吃豆的条件,撞到就吃。

voidCSnakeView:

:

OnTimer(UINTnIDEvent)

{if(Food.isfood==1)

{

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 艺术

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1