贪吃蛇小游戏(C++)

这篇具有很好参考价值的文章主要介绍了贪吃蛇小游戏(C++)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

首先我们需要下载EasyX(具体的方法在EasyX专栏中有提到)

easyX下载和绘制简单基本图形_小梁今天敲代码了吗的博客-CSDN博客

贪吃蛇这个游戏我们一定都玩过,玩家使用方向键操控一条“蛇”,蛇会朝着一个方向不断移动,玩家可以通过上下左右键改变其运动方向。同时屏幕上随机会出现各种“食物”,玩家要控制蛇去吃掉这些食物,每吃掉一个,蛇的身体就会增长一节。

想要实现这个游戏,我们主要得考虑蛇和食物

蛇:

蛇的移动方向如何实现

蛇的身体长度如何实现增长

食物:

食物如何随机生成

下面我将代码部分拆解做一个简单的说明,后附源码

首先是播放背景音乐:

将音乐的mp3格式与代码放在一个文件夹中,用以下函数调用:

贪吃蛇小游戏(C++)

#include<mmsystem.h>//头文件
#pragma comment(lib,"winmm.lib")//库文件
	//播放音乐 mci media control interface(多媒体设备接口)
	//Send 发送 String字符串
//音乐需要放在程序同一文件目录中
mciSendString("open 音乐.mp3",0,0,0);
mciSendString("play 音乐.mp3", 0, 0, 0);

 创建“精灵类”,它是“蛇类”和“食物类”的父类

这里难理解的地方是:碰撞检测(我们如何去判定蛇能吃到食物?这里采用的方法是当蛇头的左上方x,y坐标完全与食物的左上方x,y坐标相等时,我们认为蛇吃到了食物)

这个函数用于设置当前设备填充颜色。

void setfillcolor(COLORREF color);

 

这个函数用于画有边框的填充矩形。

void fillrectangle(
	int left,
	int top,
	int right,
	int bottom
);

 

//精灵类
class Sprite
{
public:
	Sprite():Sprite(0,0) {};
	Sprite(int x, int y) :m_x(x), m_y(y),m_color(RED) {};
	//绘制精灵
	virtual void draw()
	{
		//设置填充颜色
		setfillcolor(m_color);
		//绘制矩形
		fillrectangle(m_x, m_y, m_x + 10, m_y + 10);
	}
	//移动
	void moveBy(int dx, int dy)
	{
		m_x += dx;
		m_y += dy;
	}
	//碰撞检测
	bool collision(const Sprite& other)
	{
		return m_x == other.m_x && m_y == other.m_y;
	}
protected:
	int m_x;
	int m_y;
	COLORREF m_color;//颜色
};

蛇类这里移动时,将上一个格子坐标赋值给下一个格子,实现移动

push_back()函数的用法

函数将一个新的元素加到vector的最后面,位置为当前最后一个元素的下一个元素

//蛇类
class Snake : public Sprite
{
public:
	Snake():Snake(0,0) {}
	Snake(int x,int y):Sprite(x,y),dir(VK_RIGHT)
	{
		//初始化三节蛇
		nodes.push_back(Sprite(20, 0));
		nodes.push_back(Sprite(10, 0));
		nodes.push_back(Sprite(0, 0));
	}
	void draw() override
	{
		for (int i = 0; i < nodes.size(); i++)
		{
			nodes[i].draw();
		}
	}
	//蛇的身体移动
	void bodyMove()
	{
		//身体跟着蛇头移动
		for (size_t i = nodes.size()-1; i >0; i--)
		{
			nodes[i] = nodes[i - 1];
		}
		//移动蛇头
		switch (dir)
		{
		case VK_UP:
			nodes[0].moveBy(0,-10);
			break;
		case VK_DOWN:
			nodes[0].moveBy(0,10);
			break;
		case VK_LEFT:
			nodes[0].moveBy(-10, 0);
			break;
		case VK_RIGHT:
			nodes[0].moveBy(10, 0);
			break;
		}
		
	}
	bool collision(const Sprite& other)
	{
		return nodes[0].collision(other);
	}
	//蛇增加一节
	void incrment()
	{
		nodes.push_back(Sprite());
	}
private:
	//蛇只有一节吗?
	std::vector<Sprite> nodes;//蛇的所有节点

public:
	int dir;//蛇的方向
};

 食物:

为了使程序在每次执行时都能生成一个新序列的随机值,我们通常通过为随机数生成器提供一粒新的随机种子。函数srand()可以为随机数生成器播散种子。随机生成食物时,我们需要它的坐标为10的整数倍,因为蛇的身体我们设定的占10个像素,所以只能吃到坐标为10的整数倍的食物

//食物
class Food :public Sprite
{
public:
	Food() :Sprite(0, 0) 
	{
		changePos();
	}
	void draw()override
	{
		setfillcolor(m_color)
			;
		solidellipse(m_x, m_y, m_x + 10, m_y + 10);
	}
	//改变食物的坐标
	void changePos()
	{
		//随机生成坐标
		m_x = rand() % 64 * 10;
		m_y = rand() % 48 * 10;
	}
};

 游戏场景:

这里引用的函数是什么意思基本已经在代码中进行了标注

这里的switch代码是在蛇的移动过程中,让它不能掉头

switch (msg.vkcode)
			{
			case VK_UP:
				if (snake.dir != VK_DOWN)
					snake.dir = msg.vkcode;
				break;
			case VK_DOWN:
				if (snake.dir != VK_UP)
					snake.dir = msg.vkcode;
				break;
			case VK_LEFT:
				if (snake.dir != VK_RIGHT)
					snake.dir = msg.vkcode;
				break;
			case VK_RIGHT:
				if (snake.dir != VK_LEFT)
					snake.dir = msg.vkcode;
				break;
			}

 ExMessage这个结构体用于保存鼠标消息

WM_KEYDOWN EX_KEY 按键按下消息

BeginBatchDraw()这个函数用于开始批量绘图。执行后,任何绘图操作都将暂时不输出到绘图窗口上,直到执行 FlushBatchDraw 或 EndBatchDraw 才将之前的绘图输出。

void BeginBatchDraw();

 

cleardevice()这个函数使用当前背景色清空绘图设备。

void cleardevice();
/*游戏场景*/
class GameScene
{
public:
	GameScene() 
	{

	};
	void run()
	{
		BeginBatchDraw();//双缓冲绘图 防止屏幕闪烁
		cleardevice();//清屏
		snake.draw();
		food.draw();
		EndBatchDraw();
		//移动蛇,改变蛇的坐标
		snake.bodyMove();
		snakeEatFood();


		//获取消息
		ExMessage msg = { 0 };
		while (peekmessage(&msg, EX_KEY))
		{
			onMsg(msg);
		}

	}
	//改变蛇的移动方向 获取键盘按键 _getch() 
	//响应消息:鼠标消息 键盘消息
	void onMsg(const ExMessage& msg)
	{
		//如果有键盘消息(有没有按键按下)
		if (msg.message == WM_KEYDOWN)
		{
			//判断具体的是哪个按键按下 virtual key code 虚拟键码

			switch (msg.vkcode)
			{
			case VK_UP:
				if (snake.dir != VK_DOWN)
					snake.dir = msg.vkcode;
				break;
			case VK_DOWN:
				if (snake.dir != VK_UP)
					snake.dir = msg.vkcode;
				break;
			case VK_LEFT:
				if (snake.dir != VK_RIGHT)
					snake.dir = msg.vkcode;
				break;
			case VK_RIGHT:
				if (snake.dir != VK_LEFT)
					snake.dir = msg.vkcode;
				break;
			}
			
			//std::cout << msg.vkcode << std::endl;
		}

	}
	//判断蛇能否吃到食物
	void snakeEatFood()
	{
		if (snake.collision(food))//如果蛇和食物产生了碰撞
		{
			//蛇的节数增加
			snake.incrment();
			//食物重新产生在别的地方
			food.changePos();
		}
	}
private:
	Snake snake;
	Food food;

};

 最后源码如下:

#include<iostream>//标准输入输出头文件
#include<graphics.h>
#include<mmsystem.h>
#pragma comment(lib,"winmm.lib")
#include<easyx.h>
#include<vector> //顺序表
#include<ctime>
//精灵类
class Sprite
{
public:
	Sprite():Sprite(0,0) {};
	Sprite(int x, int y) :m_x(x), m_y(y),m_color(RED) {};
	//绘制精灵
	virtual void draw()
	{
		//设置填充颜色
		setfillcolor(m_color);
		//绘制矩形
		fillrectangle(m_x, m_y, m_x + 10, m_y + 10);
	}
	//移动
	void moveBy(int dx, int dy)
	{
		m_x += dx;
		m_y += dy;
	}
	//碰撞检测
	bool collision(const Sprite& other)
	{
		return m_x == other.m_x && m_y == other.m_y;
	}
protected:
	int m_x;
	int m_y;
	COLORREF m_color;//颜色
};

//蛇类
class Snake : public Sprite
{
public:
	Snake():Snake(0,0) {}
	Snake(int x,int y):Sprite(x,y),dir(VK_RIGHT)
	{
		//初始化三节蛇
		nodes.push_back(Sprite(20, 0));
		nodes.push_back(Sprite(10, 0));
		nodes.push_back(Sprite(0, 0));
	}
	void draw() override
	{
		for (int i = 0; i < nodes.size(); i++)
		{
			nodes[i].draw();
		}
	}
	//蛇的身体移动
	void bodyMove()
	{
		//身体跟着蛇头移动
		for (size_t i = nodes.size()-1; i >0; i--)
		{
			nodes[i] = nodes[i - 1];
		}
		//移动蛇头
		switch (dir)
		{
		case VK_UP:
			nodes[0].moveBy(0,-10);
			break;
		case VK_DOWN:
			nodes[0].moveBy(0,10);
			break;
		case VK_LEFT:
			nodes[0].moveBy(-10, 0);
			break;
		case VK_RIGHT:
			nodes[0].moveBy(10, 0);
			break;
		}
		
	}
	bool collision(const Sprite& other)
	{
		return nodes[0].collision(other);
	}
	//蛇增加一节
	void incrment()
	{
		nodes.push_back(Sprite());
	}
private:
	//蛇只有一节吗?
	std::vector<Sprite> nodes;//蛇的所有节点

public:
	int dir;//蛇的方向
};
//食物
class Food :public Sprite
{
public:
	Food() :Sprite(0, 0) 
	{
		changePos();
	}
	void draw()override
	{
		setfillcolor(m_color)
			;
		solidellipse(m_x, m_y, m_x + 10, m_y + 10);
	}
	//改变食物的坐标
	void changePos()
	{
		//随机生成坐标
		m_x = rand() % 64 * 10;
		m_y = rand() % 48 * 10;
	}
};
/*游戏场景*/
class GameScene
{
public:
	GameScene() 
	{

	};
	void run()
	{
		BeginBatchDraw();//双缓冲绘图 防止屏幕闪烁
		cleardevice();//清屏
		snake.draw();
		food.draw();
		EndBatchDraw();
		//移动蛇,改变蛇的坐标
		snake.bodyMove();
		snakeEatFood();


		//获取消息
		ExMessage msg = { 0 };
		while (peekmessage(&msg, EX_KEY))
		{
			onMsg(msg);
		}

	}
	//改变蛇的移动方向 获取键盘按键 _getch() 
	//响应消息:鼠标消息 键盘消息
	void onMsg(const ExMessage& msg)
	{
		//如果有键盘消息(有没有按键按下)
		if (msg.message == WM_KEYDOWN)
		{
			//判断具体的是哪个按键按下 virtual key code 虚拟键码

			switch (msg.vkcode)
			{
			case VK_UP:
				if (snake.dir != VK_DOWN)
					snake.dir = msg.vkcode;
				break;
			case VK_DOWN:
				if (snake.dir != VK_UP)
					snake.dir = msg.vkcode;
				break;
			case VK_LEFT:
				if (snake.dir != VK_RIGHT)
					snake.dir = msg.vkcode;
				break;
			case VK_RIGHT:
				if (snake.dir != VK_LEFT)
					snake.dir = msg.vkcode;
				break;
			}
			
			//std::cout << msg.vkcode << std::endl;
		}

	}
	//判断蛇能否吃到食物
	void snakeEatFood()
	{
		if (snake.collision(food))//如果蛇和食物产生了碰撞
		{
			//蛇的节数增加
			snake.incrment();
			//食物重新产生在别的地方
			food.changePos();
		}
	}
private:
	Snake snake;
	Food food;

};
int main()
{
	//初始化窗口界面
	initgraph(640,480,EW_SHOWCONSOLE);
	GameScene scene;
	scene.run();
	//设置随机数种子
	srand(time(nullptr));
	//播放音乐 mci media control interface(多媒体设备接口)
	//Send 发送 String字符串
	mciSendString("open 音乐.mp3",0,0,0);
	mciSendString("play 音乐.mp3", 0, 0, 0);

	Snake snake;
	snake.draw();
	while (true)
	{
		scene.run();
		Sleep(100);
	}
	getchar();//防止程序闪退
	return 0;
}

贪吃蛇小游戏(C++)

至此我们就实现了简单的贪吃蛇游戏,它可以上下左右移动,并在吃到食物后增长一格身体文章来源地址https://www.toymoban.com/news/detail-426909.html

到了这里,关于贪吃蛇小游戏(C++)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • QT-贪吃小游戏

    https://download.csdn.net/download/u013083044/88758860

    2024年01月19日
    浏览(51)
  • Javase | 贪吃蛇小游戏

    * 1:设计游戏图纸 * 2:设计游戏窗体 * 3:在窗体上添加面板 * 4:在面板上添加画笔方法(paintComponent方法) *5 用super调用父类的paintComponent (来每一次刷新界面) * 6:在面板上添加标题:用ImageIcon导入图片类来导入图片,然后调用有关方法 * 7:在面板上添加黑色游戏区框(

    2024年02月04日
    浏览(49)
  • Java小游戏—贪吃蛇

    摘 要 近年来,java作为一种新的编程语言,以其简单性、可移植性和平台无关性等优点,得到了各个国家广泛地认可。本文基于java技术和Eclipse开发环境,设计并实现了一个操作简单、界面美观的“贪吃蛇”游戏。“贪吃蛇”游戏是一个经典的游戏,它因操作简单、娱乐性强

    2024年02月03日
    浏览(47)
  • Python贪吃蛇小游戏

    Python贪吃蛇小游戏 若程序错误,请去终端下载random, turtle, freegames pip install random pip install turtle pip install freegames from random import randrange from turtle import * from freegames import square, vector food = vector(0, 0) snake = [vector(10, 0)] aim = vector(0, -10) def change(x, y):     \\\"\\\"\\\"Change snake direction.\\\"\\\"\\\"    

    2024年02月03日
    浏览(55)
  • 小游戏:人生中写的第一个小游戏——贪吃蛇(C语言)

            小编开了一个关于游戏的专栏,主要是运用easyx图形库进行的。        第一章:人生中写的第一个小游戏——贪吃蛇(C语言)         这个游戏的代码我在gitee上发布了,大家如果不嫌弃,可以进入这个网址进行查看和复制:https://gitee.com/rising-sun-1。      

    2024年02月09日
    浏览(61)
  • 【C语言小游戏】贪吃蛇

      使⽤C语⾔在Windows环境的控制台中模拟实现经典⼩游戏贪吃蛇 实现基本的功能: 贪吃蛇地图绘制 蛇吃⻝物的功能 (上、下、左、右⽅向键控制蛇的动作) 蛇撞墙死亡 蛇撞⾃⾝死亡 计算得分 蛇⾝加速、减速 暂停游戏 游戏指引页面 游戏页面 指针; 动态内存; 结构体;

    2024年01月19日
    浏览(41)
  • C语言——贪吃蛇小游戏

    目录 一、ncurse 1.1 为什么需要用ncurse: 1.2 ncurse的输入输出: 1.2.1 如何使用ncurse: 1.2.2 编译ncurse的程序: 1.2.3 测试输入一个按键ncurse的响应速度: 1.3 ncurse上下左右键获取: 1.3.1 如何查看宏定义的.h文件: 1.3.2 ncurse上下左右键获取: 二、地图规划 2.1 地图规划算法显示第一

    2024年02月07日
    浏览(42)
  • 项目实践---贪吃蛇小游戏(下)

    对于贪吃蛇小游戏,最主要的还是主函数部分,这里就和大家一一列举出来, 上一章已经写过头文件了,这里就不多介绍了。 首先就是打印桌面,也就是背景,则对应的代码为: 然后就是打印墙体,在打印墙体之前,要先声明一下类型,用 #define ,来定义。则对应的代码为:

    2024年04月28日
    浏览(46)
  • C语言-------实现贪吃蛇小游戏

    Windows 这个多作业系统除了协调应用程序的执行、分配内存、管理资源之外, 它同时也是一个很大的服务中心,调用这个服务中心的各种服务(每一种服务就是一个函数),可以帮应用程序达到开启视窗、描绘图形、使用周边设备等目的,由于这些函数服务的对象是应用程序

    2024年04月29日
    浏览(47)
  • 挑战!贪吃蛇小游戏的实现(2)

    在贪吃蛇小游戏的实现(1)中,我们学习了win32 相关的一些知识,本篇文章,博主将带领大家从0开始实现贪吃蛇小游戏! locale.h实现本地化 ,该头文件提供的函数用于控制C标准库中对于不同的地区会产生不一样行为的部分,如:数字量的格式,货币量的格式,字符集以及日

    2024年02月21日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包