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_UP 1
#define DIREC_DOWN 2
#define DIREC_RIGHT 3
#define DIREC_LEFT 4#define LOW_LEVEL_SLEEP 100
#define NOR_LEVEL_SLEEP 50
#define HIGH_LEVEL_SLEEP 30class CSnakeGame:public CWnd
{
public:void HeroWrite();void ReDrawBody(CPoint pt);void InitGame();CSnakeGame();virtual ~CSnakeGame();BOOL GameStart(); //游戏开始函数void InitFoods(); //初始化果实函数void SetGameLevel(int level);private:CPoint m_psFood; //当前食物坐标int m_nDirect; //当前蛇先进方向int m_nScore; //当前游戏分数int m_nlevel; //当前游戏等级int m_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_MAP
END_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++实现贪吃蛇游戏项目实战三:核心算法设计与实现(附源码和资源 可用于大作业)相关推荐
- Visual C++实现黑白棋游戏实战三:核心算法设计与实现(附源码和资源 可用于大作业)
需要源码和资源请点赞关注收藏后评论区留言私信~~~ 在前面的博客中已经讲解了黑白棋游戏的菜单和各种对话框的实现,下面将对黑白棋游戏的核心算法的设计和实现进行讲解 一.棋盘窗口类的设计 黑白棋的棋盘窗口 ...
- Visual C++黑白棋游戏项目开发一:需求分析、系统架构设计(附源码和资源 可用于大作业)
需要源码和资源请点赞关注收藏后评论区留言私信~~~ 一.黑白棋需求分析 黑白棋,游戏通过相互反转对方的棋子,最后以棋盘上谁的棋子多来判断胜负,其游戏规则比较简单,因此很容易学会,但是变化却又非常复杂, ...
- 【C#+SQL Server】实现模仿QQ的交友软件 三:申请账号窗体设计讲解(附源码和资源)
需要源码和资源请点赞关注收藏后评论区留言私信~~~ 其他几个部分文章链接如下 [C#+SQL Server]实现模仿QQ的交友软件 一:系统简介.功能展示与数据库设计(附源码和资源) [C#+SQL ...
- Python自制游戏:还原经典款贪吃蛇,表弟玩着玩着都哭了(附源码)
文章目录 一.写在前面 二.准备工作 1.用到的软件 2.用到的模块 三.来吧 展示 四.效果 五.打包成exe可执行文件 一.写在前面 贪吃蛇这个游戏,在游戏机横行的年代,基本上闲下来就会玩玩贪吃蛇 ...
- 【C#+Access+WindowsAPI】实现仿360的安全卫士 三:系统检测窗体设计(附源码和资源)
需要源码和PPT请点赞关注收藏后评论区留言私信~~~ 其他部分文章链接如下 [C#+Access+WindowsAPI]实现仿360的安全卫士 一:功能展示与系统开发环境简介(附源码和资源 [C#+A ...
- Visual C++实现黑白棋游戏项目实战二:界面的设计与实现(附源码和资源 超详细)
需要源码和资源请点赞关注收藏后评论区留言私信~~~ 黑白棋游戏的Visual C++工程采用MFC对话框模式进行开发,下面对它进行详细介绍 一.游戏菜单的实现 首先要在工程资源中添加一个菜单资源类,菜 ...
- Visual C++实现俄罗斯方块游戏实战三:核心算法设计与实现(附源码和资源)
需要源码和资源请点赞关注收藏后评论区留言私信~~~ 一.主游戏类的设计 俄罗斯方块的主游戏类负责显示游戏界面,方块游戏等级等内容,同时还要管理游戏的输入操作 可以分为以下几个模块 1:游戏界面和方块的 ...
- 贪吃蛇c语言程序 简书,C语言/C++项目源码分享—贪吃蛇
/* 项目内容:贪吃蛇 开发环境:vs2013+easyx */ 这个项目是一个小游戏-贪吃蛇项目,代码如下 #include #include //包含easyx图形库,可以使用给我们提供的一些函数 ...
- 【C#+SQL Server+打印组件】实现电商快递单打印系统 三:主窗体中的快捷菜单(附源码和资源)
需要源码请点赞关注收藏后评论区留言私信~~~ 一.快捷单设置的快捷菜单 打开主窗体AppForm的设计界面,双击主窗体的标题栏,切换到主窗体的代码页,在代码页的公共变量或方法的编写区,创建CommCl ...
最新文章
- iOS 仿看了吗应用、指南针测网速等常用工具、自定义弹出视图框架、图片裁剪、内容扩展等源码...
- 机器人学习--双目视觉测距
- 前端必知必会--JSON.stringify()犀利的第三个参数
- nginx定制header返回信息模块ngx_headers_more
- 物联网智能网关应用系统的一般设计方法
- 计算机操作系统(2):OS的发展过程
- Asp.Net微信发布菜单,出现“invalid sub button url domain hint”错误
- Java基础语法之Map
- CC攻击(N个免费代理形成的DDOS)
- WatchStor观察:冰岛身陷困境也不会停止数据中心项目
- 记录报错:java.lang.NullPointerException org.apache.jsp.test_jsp._jspInit(test_jsp.java:23)
- CSocket实现端口扫描
- 物理学的过去、现在与未来
- python pdf处理工具_NB,真PDF神处理工具!
- c语言的矩阵怎么编程,关于矩阵的编程
- 宽带拨号常见错误代码解析及故障排查
- CentOS7(8)安装/卸载MySQL
- electron对接dll
- 手游联运平台是怎样开发的?
- node节点kubelet报错 node \“xxxxx“ not found