失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > Visual C++实现贪吃蛇游戏项目实战三:核心算法设计与实现(附源码和资源 可用于大作业)

Visual C++实现贪吃蛇游戏项目实战三:核心算法设计与实现(附源码和资源 可用于大作业)

时间:2018-11-13 11:40:10

相关推荐

Visual C++实现贪吃蛇游戏项目实战三:核心算法设计与实现(附源码和资源 可用于大作业)

需要源码和资源请点赞关注收藏后评论区留言私信~~~

一、主游戏类的设计

主游戏类主要负责贪吃蛇及果实的显示和更新

果实出现的设计思路如下

1:采用随机数生成果实并出现坐标

2:判断当前生成的果实坐标是否在贪吃蛇身体范围内

3:如果在,重新生成直到不在为止,如果不在,则把坐标位置返回给调用对象

主游戏类的声明中包含了绘制蛇身函数,初始化游戏函数,随机分配果实函数以及设置当前游戏等级函数等的声明,代码如下

#ifndef __SNAKE_GAME_H__#define __SNAKE_GAME_H__//主游戏类#include "Afxtempl.h"//插入模板头文件#define GAME_LEVEL_LOW 2#define GAME_LEVEL_NOR 4#define GAME_LEVEL_HIGH 8#define DIREC_UP1#define DIREC_DOWN2#define DIREC_RIGHT 3#define DIREC_LEFT4#define LOW_LEVEL_SLEEP100#define NOR_LEVEL_SLEEP50#define HIGH_LEVEL_SLEEP30class CSnakeGame:public CWnd{public:void HeroWrite();void ReDrawBody(CPoint pt);void InitGame();CSnakeGame();virtual ~CSnakeGame();BOOL GameStart();//游戏开始函数void InitFoods();//初始化果实函数void SetGameLevel(int level);private:CPointm_psFood;//当前食物坐标intm_nDirect;//当前蛇先进方向intm_nScore;//当前游戏分数intm_nlevel;//当前游戏等级intm_nHighScore;//当前游戏最高分CArray<CPoint,CPoint> m_body;//蛇身向量protected:afx_msg void OnPaint();afx_msg void OnTimer(UINT nIDEvent);afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags);DECLARE_MESSAGE_MAP()};#endif

通过前面类的声明,已经知道主游戏类中包含的几个基本函数,如构造,析构,绘图和接收键盘输入等,这些函数是主游戏窗口类基础,用于构成对话框,处理图片的显示以及人机交互过程

#include "stdafx.h"#include "SnakeGame.h"#include "Resource.h"#include "Rule.h"#include "HeroDlg.h"CSnakeGame::CSnakeGame(){m_nScore = 0;m_psFood.x = 30;m_psFood.y = 30;m_nHighScore = 0;}CSnakeGame::~CSnakeGame(){}// 消息映射表BEGIN_MESSAGE_MAP( CSnakeGame, CWnd )//{{AFX_MSG_MAP(CSnakeGame)ON_WM_PAINT()ON_WM_TIMER()ON_WM_KEYUP()//}}AFX_MSG_MAPEND_MESSAGE_MAP()//// 初始化果实//void CSnakeGame::InitFoods(){int m_ysX,m_ysY;while(1){m_ysX=rand()%28;//随机生成横坐标使其与贪吃蛇的身体可以接上m_ysY=rand()%28;//随机生成纵坐标使其与贪吃蛇的身体可以接上for(int i=0;i<=m_body.GetUpperBound();i++){CPoint ysPoint1=m_body.GetAt(i);//获取贪吃蛇的身体坐标if(ysPoint1.x!=m_ysX||ysPoint1.y!=m_ysY)//如果身体的横坐标或纵坐标与果实的横纵坐标相同{m_psFood = CPoint(m_ysX, m_ysY);//将随机出现的坐标记录为果实坐标return;}}}}//// 设置游戏等级//void CSnakeGame::SetGameLevel(int level){m_nlevel = level;}//// 开始游戏函数//BOOL CSnakeGame::GameStart(){int nSleep = LOW_LEVEL_SLEEP;char pszTmp[128] = {0};switch(m_nlevel){case GAME_LEVEL_HIGH:nSleep = HIGH_LEVEL_SLEEP;break;case GAME_LEVEL_NOR:nSleep = NOR_LEVEL_SLEEP;break;}GetPrivateProfileString("HERO", "score", "0", pszTmp, 127, ".\\hero.ini");m_nHighScore = atoi(pszTmp);SetTimer(1, nSleep, NULL);InitGame();return TRUE;}//// 处理WM_PAINT消息//void CSnakeGame::OnPaint(){CPaintDC dc( this );CDC MemDC;MemDC.CreateCompatibleDC( &dc );// 装载背景CBitmap bmp;CPen pen;bmp.LoadBitmap( IDB_BMP_BJ );pen.CreatePen( PS_SOLID, 1, 0xff );MemDC.SelectObject( &bmp );MemDC.SelectObject( &pen );MemDC.SetROP2( R2_NOTXORPEN );CString ysStr; //定义字符串用于显示游戏时间得分等字MemDC.SetBkMode(TRANSPARENT); //设置字体背景MemDC.SetTextColor(67); //设置字体颜色ysStr.Format("当前得分:%d",m_nScore);//初始化字符串MemDC.TextOut(30,50,ysStr);//输出文本switch(m_nlevel) //根据等级判断{case GAME_LEVEL_LOW://如果是初级ysStr.Format("当前等级: 初 级");break;case GAME_LEVEL_NOR://如果是中级ysStr.Format("当前等级: 中 级");break;case GAME_LEVEL_HIGH://如果是高级ysStr.Format("当前等级: 高 级");break;}MemDC.TextOut(30,30,ysStr);//绘制蛇的样式CPen yspen;yspen.CreatePen(1,1,RGB(255,255,255)); //定义白色画笔绘制蛇的边框MemDC.SelectObject(&yspen);CBrush ysbrush;//int k=m_body.GetUpperBound()+2; //设置一个变量存储贪吃蛇的身体长度if(k<=10) //如果小于10,那么就为绿色{ysbrush.CreateSolidBrush(RGB(0,255,0)); MemDC.SelectObject(&ysbrush);//绘制果实MemDC.Rectangle(CRect(10+m_psFood.y*10,120+m_psFood.x*10,10+(m_psFood.y+1)*10,120+(m_psFood.x+1)*10));}else if(k>10&&k<=20) //如果在10和20之间,那么就为绿色{ysbrush.CreateSolidBrush(RGB(0,0,255)); MemDC.SelectObject(&ysbrush);//绘制果实MemDC.Rectangle(CRect(10+m_psFood.y*10,120+m_psFood.x*10,10+(m_psFood.y+1)*10,120+(m_psFood.x+1)*10));}else if(k>20&&k<=30) //如果在20和30之间,那么就为绿色{ysbrush.CreateSolidBrush(RGB(255,255,0)); MemDC.SelectObject(&ysbrush);//绘制果实MemDC.Rectangle(CRect(10+m_psFood.y*10,120+m_psFood.x*10,10+(m_psFood.y+1)*10,120+(m_psFood.x+1)*10));}else //其余情况均为红色{ysbrush.CreateSolidBrush(RGB(255,0,0)); MemDC.SelectObject(&ysbrush);//绘制果实MemDC.Rectangle(CRect(10+m_psFood.y*10,120+m_psFood.x*10,10+(m_psFood.y+1)*10,120+(m_psFood.x+1)*10));}//初始化点数组for(int i=0;i<=m_body.GetUpperBound();i++){CPoint ysPoint=m_body.GetAt(i);MemDC.Rectangle(CRect(10+ysPoint.y*10,120+ysPoint.x*10,10+(ysPoint.y+1)*10,120+(ysPoint.x+1)*10));}dc.BitBlt( 0, 0, 325, 425, &MemDC,0, 0, SRCCOPY );}//// 处理按键消息//void CSnakeGame::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags){switch(nChar){case VK_UP: //按向上键m_nDirect=DIREC_UP; //控制方向变量为DIREC_UPbreak;case VK_DOWN: //按向下键m_nDirect=DIREC_DOWN;//控制方向变量为DIREC_DOWNbreak;case VK_LEFT: //按向左键m_nDirect=DIREC_LEFT;//控制方向变量为DIREC_LEFTbreak;case VK_RIGHT://按向右键m_nDirect=DIREC_RIGHT; //控制方向变量为DIREC_RIGHTbreak;default:break;}}//// 定时器响应函数//void CSnakeGame::OnTimer(UINT nIDEvent) {CPoint ysPoint=m_body.GetAt(0);//获取蛇身的第一个点坐标BOOL bTag = FALSE; //定义判断死亡的变量CRule rule; //游戏规则类switch(m_nDirect) //根据键盘按下键来选择蛇移动的方向{case DIREC_DOWN: //方向变量向下ysPoint.x++; //点纵坐标自加break;case DIREC_UP://方向变量向上ysPoint.x--; //点纵坐标自减break;case DIREC_RIGHT: //方向变量向右ysPoint.y++; //点横坐标自加break;case DIREC_LEFT: //方向变量向左ysPoint.y--; //点横坐标自减break;}if(rule.IsOver(ysPoint, m_body))//游戏结束{KillTimer(1);//关闭定时器if(m_nScore > m_nHighScore)//超过最高分{HeroWrite();//写英雄榜}else{AfxMessageBox("游戏结束,你的分数太低了,没有能进入英雄榜");}}else{m_body.InsertAt(0,ysPoint); //将新点添加到蛇的身体中ReDrawBody(ysPoint); //重绘蛇的身体if(ysPoint.x==m_psFood.x&&ysPoint.y==m_psFood.y) //如果蛇的身体与果实坐标重合{int nlen=m_body.GetUpperBound();//获取蛇身体的长度m_nScore = m_nlevel * (nlen-3);//统计分数InitFoods(); //再出现下一个果实Invalidate(); //窗口重绘}else{CPoint pt=m_body.GetAt(m_body.GetUpperBound());//将最后一个赋给ptm_body.RemoveAt(m_body.GetUpperBound()); //将移出最后一个ReDrawBody(pt); //重新绘制pt这点}}}//// 初始化游戏//void CSnakeGame::InitGame(){m_body.RemoveAll();m_body.Add(CPoint(3, 8));m_body.Add(CPoint(3, 7));m_body.Add(CPoint(3, 6));m_body.Add(CPoint(3, 5));srand((unsigned)time(NULL)); //初始化随机数生成器m_nDirect = DIREC_RIGHT; //初始时向右m_nScore = 0; //初始化分数InitFoods(); //初始化果实函数Invalidate();//重绘窗口}////重绘指定点//void CSnakeGame::ReDrawBody(CPoint pt){InvalidateRect(CRect(10+pt.y*10,120+pt.x*10,10+(pt.y+1)*10,120+(pt.x+1)*10));}//// 英雄榜写入及弹出//void CSnakeGame::HeroWrite(){CHeroDlg dlg;dlg.SetWriteFlg(TRUE);//设置可标志dlg.m_level = m_nlevel;//设置等级dlg.m_score = m_nScore;//设置分数dlg.DoModal();//弹出对话框}

二、游戏规则类的实现

游戏规则类,主要负责游戏规则的处理,在贪吃蛇游戏中,主要有如下两种规则需要实现

1:当贪吃蛇碰到四周的边界时,认定贪吃蛇死亡,游戏结束

2:当贪吃蛇碰到自己的身体时,认定贪吃蛇死亡,游戏结束

要实现这两个规则,只需要对贪吃蛇的行走路径进行判断,每走一步时对当前蛇头位置进行判断,如果蛇头的坐标超出边界或者与贪吃蛇BODY向量中的某个坐标数据相同时,就认定贪吃蛇死亡

游戏规则类实现代码如下

#ifndef __RULE_H__#define __RULE_H__#include <afxtempl.h>#define MAX_POINT 29#define MIN_POINT 0class CRule{public:BOOL IsOver(CPoint &pt, CArray<CPoint, CPoint> &body);//判断当前点是否为游戏结束};#endif

在游戏规则类的游戏结束判断接口函数中,通过如下办法实现L:

先对当前蛇身数组进行遍历,判断如果其中有一个纵坐标多余最下端边框或者少于最上端边框,则说明游戏结束,再判断如果其中有一个横坐标多余最右端边框或者最左端边框,也说明游戏结束,如果都不是就直接返回不是游戏结束,代码如下

#include "stdafx.h"#include "Rule.h"BOOL CRule::IsOver(CPoint &pt, CArray<CPoint, CPoint> &body){if(pt.x>=MAX_POINT || pt.x<MIN_POINT) //如果纵坐标多于最下端边框或者少于最上端边框{return TRUE; //判断死亡}else if(pt.y>=MAX_POINT || pt.y<MIN_POINT) //横坐标多于最右端边框{return TRUE; //判断死亡}for(int i=0;i<=body.GetUpperBound();i++){CPoint pt1 = body.GetAt(i);//将蛇身体的坐标传递给新定义的点if(pt.x==pt1.x&&pt.y==pt1.y) //如果两点完全相同,说明蛇碰到身体{return TRUE; //判断死亡}}return FALSE;}

创作不易 觉得有帮助请点赞关注收藏~~~

如果觉得《Visual C++实现贪吃蛇游戏项目实战三:核心算法设计与实现(附源码和资源 可用于大作业)》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。