评论

收藏

MFC实现贪吃蛇

游戏开发 游戏开发 发布于:2021-06-27 12:43 | 阅读数:358 | 评论:0

贪吃蛇游戏的实现
一、前期准备
类的定义
1、位置(点)类的定义
class Point
{
public:
Point(int x = 0, int y = 0);
int getPointx();  //获得X轴位置
int getPointy();  //获得Y轴位置
bool changex(int a);  //改变X轴位置
bool changey(int b);  //改变Y轴位置
bool cmp(Point &a);  //比较
private:
int x, y;  //X、Y轴
};
2、食物类的定义
class Food
{
public:
Food();
void draw(CDC* dc);   //画食物
Point init();//初始化位置
friend  Snake;  
private:
Point x;
};
3、蛇类的定义
class Snake
{
public:
friend class CTCSnakeView;
Snake(Point head, int d = 2, int len = 1);
~Snake() {
}
void drawSnake(CDC *dc);  //画蛇
bool eatFood(int x, int y); //吃食物
bool move(Food &food); //游走
void changeD(int);  //改变方向
bool isHit();
int getD() {
return direct;
}    // 获取方向
Point getH() {
return head;
}    //获取头位置
private:
Point head;  //蛇头位置
int direct;  //前进方向
vector<Point> body; // 蛇身位置
int length; //蛇长
bool isEat();  //判断是否吃到自己
//蛇身宽度为10像素
};
  开发工具 VS2019
二、实现思路
1、建立一个单文档文件
DSC0000.jpg
DSC0001.jpg

2、完成对类的声明和实现
  点类的实现
Point::Point(int x, int y)
{
this->x &#61; x;
this->y &#61; y;
}
int Point::getPointx() {
return  x;
}
int Point::getPointy() {
return y;
}
bool Point::changex(int a)
{
x &#61; a;
return true;
}
bool Point::changey(int b)
{
y &#61; b;
return true;
}
bool Point::cmp(Point& a) {
if (a.x &#61;&#61; x && a.y &#61;&#61; y)
return true;
return false;
}
  食物类的实现
Food::Food()
{
srand(time(NULL));
int a &#61; rand() % 320 &#43; 100;
a -&#61; a % 10;
int b &#61; rand() % 320 &#43; 100;
b -&#61; b % 10;
x.changex(a);
x.changey(b);
}
void Food::draw(CDC* dc)
{
CBrush brush;
brush.CreateSolidBrush(RGB(0, 0, 255));
dc->FillRect(CRect(x.getPointx(), x.getPointy(), x.getPointx() &#43; 10, x.getPointy() &#43; 10), &brush);
brush.DeleteObject();
}
Point Food::init()
{
srand(time(NULL));  //设置种子
//生成40-420之间的随机数
int a &#61; rand() % 380 &#43; 40;
a -&#61; a % 10;
int b &#61; rand() % 380 &#43; 40;
b -&#61; b % 10;
x.changex(a);
x.changey(b);
return x;
}
  贪吃蛇类的定义
Snake::Snake(Point head, int d, int len):head(60, 60), direct(d), length(len)
{
body.push_back(Point(50, 60));
}
void Snake::drawSnake(CDC * dc)
{
CBrush brush;
brush.CreateSolidBrush(RGB(0, 255, 0));
dc->FillRect(CRect(head.getPointx(), head.getPointy(), head.getPointx()&#43;10, head.getPointy()&#43;10), &brush);
brush.DeleteObject();
brush.CreateSolidBrush(RGB(255, 0, 0));
for (int i &#61; length - 1; i >&#61; 0; i--) {
dc->FillRect(CRect(body[i].getPointx(), body[i].getPointy(), body[i].getPointx() &#43; 10, body[i].getPointy() &#43; 10), &brush);
}
brush.DeleteObject();
}
bool Snake::isHit() {
if (head.getPointx() <&#61; 30 || head.getPointx() >&#61; 420)
return true;
if (head.getPointy() <&#61; 30 || head.getPointy() >&#61; 420)
return true;
return false;
}
bool Snake::move(Food &food)
{
int i &#61; length;
if (isEat())
{
return false;
}
if (isHit())
{
return false;
}
if (eatFood(food.x.getPointx(), food.x.getPointy())) {
Point n &#61; food.init();
if (n.cmp(head)) 
n &#61; food.init();
while (1) {
i &#61; length;
for (i--; i >&#61; 0; i--) {
if (body[i].cmp((n))) {
n &#61; food.init();
break;
}
}
if (i < 0)
break;
}
Point t(body[length - 1].getPointx(), body[length - 1].getPointy());
body.push_back(t);
length&#43;&#43;;
return true;
}
i &#61; length;
switch (direct)
{
case 1: {
for (i--; i >&#61; 1; i--)
{
body[i].changex(body[i - 1].getPointx());
body[i].changey(body[i - 1].getPointy());
}
body[0].changex(head.getPointx());
body[0].changey(head.getPointy());
head.changey(head.getPointy() - 10);
break;
}
case 2: {
for (i--; i >&#61; 1; i--)
{
body[i].changex(body[i - 1].getPointx());
body[i].changey(body[i - 1].getPointy());
}
body[0].changex(head.getPointx());
body[0].changey(head.getPointy());
head.changex(head.getPointx() &#43; 10);
break;
}
case 3: {
for (i--; i >&#61; 1; i--)
{
body[i].changex(body[i - 1].getPointx());
body[i].changey(body[i - 1].getPointy());
}
body[0].changex(head.getPointx());
body[0].changey(head.getPointy());
head.changey(head.getPointy() &#43; 10);
break;
}
case 4: {
for (i--; i >&#61; 1; i--)
{
body[i].changex(body[i - 1].getPointx());
body[i].changey(body[i - 1].getPointy());
}
body[0].changex(head.getPointx());
body[0].changey(head.getPointy());
head.changex(head.getPointx() - 10);
break;
}
}
return true;
}
bool Snake::isEat()
{
int x &#61; head.getPointx();
int y &#61; head.getPointy();
int i &#61; length;
if (i > 3) {
for (i-- ; i >&#61; 0; i--)
{
if (head.getPointx() &#61;&#61; body[i].getPointx() && head.getPointy() &#61;&#61; body[i].getPointy())
return true;
}
}
return false;
}
bool Snake::eatFood(int x, int y)
{
if (head.getPointx() &#61;&#61; x && head.getPointy() &#61;&#61; y)
return true;
return false;
}
void Snake::changeD(int a)
{
direct &#61; a;
}
3、对贪吃蛇、食物、界面的绘制
  建立类向导
DSC0002.jpg
对ondraw()虚函数进行编写
DSC0003.jpg
DSC0004.jpg
  在绘制过程中还需要使用双缓存技术&#xff0c;可以自行了解一下。
4、初始化游戏
  我对初始化游戏有两种方法
方法一&#xff1a; 在OnInitialUpdate()函数内用SetTimer(1, 1000, NULL);
DSC0005.png
方法二 &#xff1a;在菜单内加入开始游戏
DSC0006.jpg
实现&#xff1a;
在资源管理器内双击TCsnake.rc
DSC0007.jpg
DSC0008.png
对菜单进行编辑
DSC0009.jpg
可以写入自己想要的&#xff0c;然后添加事件处理程序
DSC00010.jpg
类列表选择CTCSnakeView&#xff0c;消息类型COMMAND&#xff0c;函数名自定义
DSC00011.jpg
在生成的函数内用settimer()达到开始游戏的效果
DSC00012.jpg
5、实现蛇的移动效果
  通过OnTimer()、SetTimer()、Invalidate()和KillTimer()的配合实现
6、通过按键改变蛇的移动方向
  首先添加一个OnKeyDown()函数
DSC00013.jpg
再在函数内判断按下的键所对应的方向&#xff0c;最后进行一个改变方向的操作。
  







以上就是我实现贪吃蛇的基础步骤&#xff0c;初学MFC&#xff0c;很多地方没有考虑周全。内容很多只是粗略介绍实现过程&#xff0c;具体的实现过程还需要查看源码&#xff0c;用到的一些虚函数和消息的详解大家应该可以自行查到。作品仅作记录
  下面附上源码
源码地址&#xff1a; https://gitee.com/gg_8_0/the-greedy-snake-of-mfc.git
                                                           
关注下面的标签,发现更多相似文章