用mfc设计贪吃蛇游戏源代码,最好有解析

用mfc设计贪吃蛇游戏源代码,最好有解析,第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.基于对话框的应用程序,响应按键消息需在PreTranslateMessage里,而不是像文档视图模式那样在OnKeyDown里响应。

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

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

2.添加如下函数和变量

1 void HuaFangGe(int bianChang, int gridShumu) //如在400*400的方格里绘制20*20个格子,则bianChang = 400;gridShumu = 20

2 void InitSnackSite() //初始化蛇的位置

3

4 int snakeLength //表示蛇的长度

5 int foodX //食物的X位置

6 int foodY //食物的Y位闹没唯置

7 bool start //标志是否开始

8 bool reStart //标志是否重新开始

9

10 struct SNAKE

11 {

12 int x

13 int y

14 char direction //某位置的方向为前一个位置相对于该位置的方向,由SetDirection()确定

15 }snake[200]

16

17 void DrawRed(int x, int y) //指定点0*0到20*20,画相应颜色,下同(红头绿身蓝尾)

18 void DrawGreen(int x, int y)

19 void DrawBlue(int x, int y)

20 void DrawBlack(int x, int y) //根据SetFoodXY()所确定的foodX和foodY来画食物。

21

22 void DrawSnakeFood() //根据数组snakeSite数组的标识信息类绘制蛇的形状位置颜色。

23 void SetFoodXY() //随机绘制食物的XY位置

24

25 bool leftRight //确定是否能上下走(蛇本身在上下走,再按上下就无用了)

26 bool upDown //确定是否能左右走(蛇本身在左右走,再按左右就无用了)

27

28 void MoveSite() //蛇移动过程中,设置“除蛇头”外各节的x和y的位置,顺序前移。

29 void SetDirection() //蛇移动过程中,设置“除蛇头”外各节的方向

30

31 void TurnLeft() //当蛇左转时

32 void TurnRight() //当蛇右转时

33 void GoUp() //当蛇向上时

34 void GoDown() //当蛇向下时

可以参考这里:http://www.cnblogs.com/jncpp/archive/2012/07/24/2606908.html

【原创】基于MFC的 贪吃蛇 小游戏的实现,附源码下载

首先mfc不是文件

,它是微软利用visual

stutio

开发工具所建立的一些类供用户使用。安装好vc,这些类就是可以使用掘誉纳的。建立判没mfc程序步骤如下:打开vc运行环境,选择文件,点击新建,选择工程

点击

MFC

APPWizard(exe)

这个选项,填写一个工程的名字,制定好位置,打击确定,在d出的对话框中

可以再

单文档,多重文档,基本对话框

中任选一项

即可

,点击完成

,这样

,一个简答的mfc程序虚锋就创建好了

,你可以直接编译

,运行

,看看效果

3. 要点分析

蛇的活动区域是由若干个小方格组成的。当这些小方格呈现灰色时,便表示蛇身。设整个区域由m×n个方格组成,最左上角的方格坐标为(0, 0)。蛇是由若干个邻的方格组成的,将这些方格的坐标依蛇头至蛇尾的次序存入到一个数组中便代表了蛇身。当蛇在游戏区域中“游动”一格时,所对应的数组 *** 作应该是,将新的位置坐标插入到数组头部,同时将数组中最后一个元素删除。这项工作可以用一个一般的数组来完成,但当进行插入 *** 作时需要自己移动数组中的元素;也可以使用CArray来完成这些工作,CArray的成员函数提供了需要的 *** 作,这样做简单一些。

4. 解题步骤

(1)新建工程Snake,在MFC的向导第一步选择Single Document,按Finish结束。

(2)选择ResourceView窗口,打开菜单编辑器,在顶层菜单上添加一个名为“游戏”的d出式菜单,该菜单下再添加一个名为“开始”的子菜单,其ID为ID_GAME_START,如图1所示。

图1 菜单的设计

(3)在ClassWizard中为刚才编辑好的菜单添加消息处理函数。打开ClassWizard,选中Message Maps页。在Class Name中选择CSnakeView,在Object ID中选择ID_GAME_ START,在Messages中选择COMMAND,添加消息处理函数。

(4)在ClassWizard中添加键盘消息处理函数。打开ClassWizard,选中Message Maps页。在Class Name中选择CSnakeView,在Object ID中选择CSnakeView,在Messages中选择WM_KeyDown,添加消息处理函数。

(5)在ClassWizard中定时器消息添加处理函数。打开ClassWizard,选中Message Maps页。在Class Name中选择CSnakeView,在Object ID中选择CSnakeView,在Messages中选择WM_Timer,侍粗局添加消息处理函数。

(6)编辑生成的代码,完成程序。

4. 源程序清单

(1) 选择ClassView窗口,双击CSnakeView类,添加如下成员变量。并添加头文件:

#include <Afxtempl.h>

class CSnakeView : public CView

{

//此处略去若干行由系统生成的代码

private:

void ReDisplay(CPoint pPoint)

void IniGame()

void IniAim()

int m_nLeft, m_nTop, m_nWidth, m_nHeight, m_nSize// 起始坐标,宽/高度老让(格数),每格大小

int m_nDirect// 当前方向

// 1-右,2-左,3-下,4-上

CPoint m_pAim// 当前目标坐标

CArray <CPoint, CPoint >m_aBody// 蛇身

int m_nGameStatus// 游戏状态: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 i=0i <= m_aBody. GetUpperBound ( )i++)

{

CPoint uPoint = m_aBody. GetAt (i)

if (uPoint. x == uX ||uPoint. y == uY ) // 目标与蛇身重合

{

uTag = 1

break

}

}

if (uTag == 0)

break

}

m_pAim = CPoint (uX, uY)// 产生的目标存放在成员变量中

}

// 该函数对游戏初始化,定义游戏的初始状态

void CSnakeView::IniGame()

{

// 游凳茄戏区域

m_nLeft = 20

m_nTop = 20

m_nWidth = 40

m_nHeight = 30

m_nSize = 10

// 游初始状态

m_nGameStatus = 0

m_nDirect = 1

m_nCount = 0

// 初始化蛇身

m_aBody. RemoveAll ( )

m_aBody. Add ( CPoint (2, 7) )

m_aBody. Add ( CPoint (2, 6) )

m_aBody. Add ( CPoint (2, 5) )

m_aBody. Add ( CPoint (2, 4) )

// 计时器清零

m_nTime = 0

m_nTime1 = 0

// 初始化随机数发生器

srand ( (unsigned) time (NULL) )

// 产生一个目标

IniAim ( )

}

// 刷新游戏区域中pPoint处的一个小方格

void CSnakeView::ReDisplay(CPoint pPoint)

{

InvalidateRect (CRect (m_nLeft + pPoint. y * m_nSize, m_nTop + pPoint. x * m_nSize,

m_nLeft + (pPoint. y + 1) * m_nSize, m_nTop + (pPoint. x + 1) * m_nSize) )

}

(3)修改CSnakeView的构造函数,完成游戏的初始化。

CSnakeView::CSnakeView()

{

IniGame()

}

(4)在OnDraw中加入代码,显示游戏界面。

void CSnakeView::OnDraw(CDC* pDC)

{

CSnakeDoc* pDoc = GetDocument()

ASSERT_VALID(pDoc)

// TODO: add draw code for native data here

// 画游戏区域

pDC ->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 ("当前得分: % 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=0i<= m_aBody. GetUpperBound ()i++)

{

CPoint uPoint = m_aBody. GetAt (i)

pDC ->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)为键盘按键消息处理函数添加代码。

// 根据按下的方向键设置代表不同方向的值

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::OnTimer(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: // right

uPoint. y++

if (uPoint. y >= m_nWidth)

uTag = 1

break

case 2: // left

uPoint. y--

if (uPoint. y <0)

uTag = 1

break

case 3: // down

uPoint. x++

if (uPoint. x >= m_nHeight)

uTag = 1

break

case 4: // up

uPoint. x--

if (uPoint. x <0)

uTag = 1

break

}

if (uTag ==0) // 判断蛇是否碰到了自身

{

for (int i=0i <= 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)// 新的蛇头的位置

ReDisplay (uPoint)

if (uPoint. x == m_pAim. x &&uPoint. y == m_pAim. y) // 碰上目标

{

m_nCount++

IniAim ( )

Invalidate ( )

}

else

{

CPoint uPoint1 = m_aBody. GetAt (m_aBody.GetUpperBound ( ) )

m_aBody. RemoveAt (m_aBody.GetUpperBound ( ) )

ReDisplay (uPoint1)

}

}

else // 游戏结束

{

KillTimer(1)

AfxMessageBox("Fail!")

}

CView::OnTimer(nIDEvent)

}


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/bake/8037336.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-12
下一篇2023-04-12

发表评论

登录后才能评论

评论列表(0条)

    保存