贪吃蛇(C++)

发布于:2024-05-16 ⋅ 阅读:(50) ⋅ 点赞:(0)

使用EasyX图形库绘制,在VC中安装,EasyX官网:EasyX Graphics Library for C++

EasyX官方文档:EasyX 文档 - 使用教程

#include<iostream>
#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& ohter)
	{
		return m_x == ohter.m_x && m_y == ohter.m_y;
	}
	bool coollisionWall()
	{
		return m_x > 640 || m_x < 0 || m_y>480 || m_y < 0;
	}
protected:
	int m_y;
	int m_x;
	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);
	}
	//碰撞墙壁
	bool die()
	{
		return nodes[0].coollisionWall();
	}
	//蛇增加一节
	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;//食物坐标为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 };
		if(peekmessage(&msg, EX_KEY))
		{
			onMsg(msg);		
		}
	}
	//响应消息:鼠标消息,键盘消息
	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;
			}
			
		}
	}
	//判断蛇能否吃到食物
	void snakeEatFood()
	{
		if (snake.collision(food))//如果蛇和食物产生碰撞
		{
			//蛇的节数增加
			snake.incrment();
			//产生新的食物
			food.changePos();
		}
	}
	//判断蛇是否碰到墙壁,如果碰到了游戏结束
	bool snakeDie()
	{
		if (snake.die())
		{
			cleardevice();//清除屏幕
			outtextxy(250, 200, L"GAME OVER!");

			return true;
		}
		return false;
	}
private:
	Snake snake;//创建蛇
	Food food;//食物

};

int main() {
	//绘制窗口
	initgraph(640, 480);
	//设置随机数种子
	srand(time(nullptr));

	GameScene scene;
	while (true)
	{
		scene.run();
		//是否死亡
		if (scene.snakeDie())
		{
			break;
		}
		Sleep(100);	
	}	
	getchar();
	return 0;
}