基于C++和EasyX 实现的《双人贪吃蛇》小游戏,你不找个小伙伴陪你一起玩吗?

两条蛇实现原理:先定义好一条蛇,然后派生出另外一条蛇,重要第二条蛇的移动方向的方法,换成键盘上的另外四个键,然后就是正常的游戏判断,两条蛇相碰的判断等等 . . .

素材就是一个背景加上一个音乐,其它的都是基于 EasyX 里的方法画出来的
在这里插入图片描述

游戏效果如下所示:

小游戏制作贪吃蛇


代码如下所示:

#include <iostream>		
#include <graphics.h>	
#include <ctime>
#include <conio.h>
#include <cstdlib>
#include <cmath>
#include <mmsystem.h>
#pragma comment (lib,"winmm")

void InitGame();	//初始化游戏

const int WIDTH = 640;
const int HEIGHT = 480;

class Snake		//	1  红色		2	绿色
{
private:
	const static int NUM = 100;	//最大节数

	struct Coord	//每一节的坐标
	{
		int x;
		int y;
	};

	int s_count;		//初始为3节
	int fruit_x, fruit_y;	//果实的位置
	Coord snake[NUM];	//一共多少节

protected:
	enum Direction { Up = 72, Down = 80, Left = 75, Right = 77 };	//枚举方向

	Direction direction;		//默认为左方向

public:
	//构造
	Snake();
	//析构
	virtual ~Snake();
	//初始蛇 和 果实的坐标
	void InitSnakeFruitCoord();
	//移动  (改变坐标)	画蛇 判断吃果实
	void Move();
	//刷新果实 位置
	void RefreshFruit();
	//改变蛇的方向
	virtual void ChangeDirection(const char& ch);
	//判断游戏 输赢
	void JudgeWinLose(const Snake& op, const int flag)const;

};

class Snake1 :public Snake		// 继承一个类   达到两条蛇
{
public:
	//构造
	Snake1();

	virtual void ChangeDirection(const char& ch);
};




int main()
{

	srand((unsigned)time(0));		//种下随机数的种子
	DWORD t1 = GetTickCount(), tt1;		//判断是否可以移动

	Snake snake1;	//两条蛇
	Snake1 snake2;
	InitGame();

	snake1.InitSnakeFruitCoord();	//画出蛇刚开始的位置
	snake2.InitSnakeFruitCoord();

	while (1)
	{

		if (_kbhit())			//判断改变位置
		{
			char ch = _getch();
			snake1.ChangeDirection(ch);
			snake2.ChangeDirection(ch);
		}

		tt1 = GetTickCount();
		if (tt1 - t1 > 100)		//自移
		{
			setfillcolor(RED);
			snake1.Move();
			setfillcolor(GREEN);
			snake2.Move();
			t1 = tt1;
		}

		snake1.JudgeWinLose(snake2, 1);
		snake2.JudgeWinLose(snake1, 2);
	}


	return 0;
}


Snake::Snake() :direction(Left), s_count(4), fruit_x(0), fruit_y(0)
{
	int x = (rand() % (WIDTH - 100) + 50) / 15 * 15;		//蛇的初始坐标
	int y = (rand() % (HEIGHT - 150) + 50) / 15 * 15;
	for (int i = 0; i < s_count; i++)
		snake[i] = { (i * 15) + x, y };
}

Snake1::Snake1() :Snake() {}  //  使用默认构造 函数    Snake()  ----

Snake::~Snake() {}

void InitGame()
{
	initgraph(WIDTH, HEIGHT);
	MOUSEMSG msg;

	mciSendString("open music.mp3 alias huameng", 0, 0, 0);
	mciSendString("play huameng repeat", 0, 0, 0);

	loadimage(nullptr, "start_background.jpg", WIDTH, HEIGHT);


	std::cin.get();
	setbkcolor(RGB(255, 128, 192));
	cleardevice();

	settextcolor(RED);

	settextstyle(40, 25, "楷体");
	outtextxy(200, 100, "开始游戏");
	setlinecolor(RGB(155, 155, 0));
	rectangle(190, 90, 410, 145);		//------

	settextstyle(20, 10, "楷体");
	settextcolor(RGB(50, 128, 255));
	outtextxy(130, 200, "游 戏 规 则 :");
	outtextxy(180, 230, "玩家一:小红  控制:4个光标键");
	outtextxy(180, 260, "玩家二:小绿  控制:W A S D");
	outtextxy(80, 320, "胜利条件:1.对方触碰边界 2.对方触碰己方身体");
	outtextxy(180, 355, "3.吃满果实(100个) >> __ <<");
	outtextxy(170, 400, "注: 同灰余烬 算小绿 赢 !!!");

	settextstyle(40, 25, "楷体");
	while (1)
	{
		msg = GetMouseMsg();
		int x = msg.x;		//rectangle(190,90,410,145);		长 220 宽 55
		int y = msg.y;


		if (x - 190 < 220 && x - 190 > 0 && y - 90 > 0 && y - 90 <= 55 && msg.mkLButton)
			break;
		else if (x - 190 < 220 && x - 190 > 0 && y - 90 > 0 && y - 90 <= 55)
		{
			settextcolor(RGB(0, 255, 255));
			outtextxy(200, 100, "开始游戏");
		}
		else
		{
			settextcolor(RED);
			outtextxy(200, 100, "开始游戏");
		}

	}

	setbkcolor(RGB(0, 255, 255));
	cleardevice();
}

void Snake::RefreshFruit()
{
	fruit_x = (rand() % (WIDTH - 100) + 50) / 15 * 15;		//	刷新位置
	fruit_y = (rand() % (HEIGHT - 100) + 50) / 15 * 15;
}

void Snake::InitSnakeFruitCoord()
{
	for (int i = 0; i < s_count; i++)
		solidrectangle(snake[i].x, snake[i].y, snake[i].x + 15, snake[i].y + 15);

	fruit_x = (rand() % (WIDTH - 100) + 50) / 15 * 15;
	fruit_y = (rand() % (HEIGHT - 100) + 50) / 15 * 15;
}

void Snake::Move()
{
	clearrectangle(snake[s_count - 1].x, snake[s_count - 1].y, snake[s_count - 1].x + 15, snake[s_count - 1].y + 15);

	for (int i = s_count - 1; i > 0; i--)
	{
		snake[i].x = snake[i - 1].x;
		snake[i].y = snake[i - 1].y;
	}

	switch (direction)
	{
	case Snake::Up:
		snake[0].y -= 15;
		break;
	case Snake::Down:
		snake[0].y += 15;
		break;
	case Snake::Left:
		snake[0].x -= 15;
		break;
	case Snake::Right:
		snake[0].x += 15;
		break;
	}

	for (int i = 0; i < s_count; i++)
		solidrectangle(snake[i].x, snake[i].y, snake[i].x + 15, snake[i].y + 15);

	solidrectangle(fruit_x, fruit_y, fruit_x + 15, fruit_y + 15);
	if (snake[0].x == fruit_x && snake[0].y == fruit_y)
	{
		RefreshFruit();
		Move();			//防止吃到果实  卡顿
		s_count++;
	}
}

void Snake::ChangeDirection(const char& ch)
{
	switch (ch)
	{
	case 72:direction = Up; break;
	case 75:direction = Left; break;
	case 77:direction = Right; break;
	case 80:direction = Down; break;
	}
}

void Snake1::ChangeDirection(const char& ch)
{
	switch (ch)
	{
	case 'W':direction = Up; break;
	case 'A':direction = Left; break;
	case 'D':direction = Right; break;
	case 'S':direction = Down; break;
	}
}

void Snake::JudgeWinLose(const Snake& op, const int flag)const
{
	if (flag == 1)
	{
		if (snake[0].x <= 0 || snake[0].x >= WIDTH || snake[0].y <= 0 || snake[0].y >= HEIGHT || s_count >= 99)
		{
			MessageBox(nullptr, "小绿胜利了 >>_<<", "游戏结束!!", MB_OK);
			exit(0);
		}
		else
			for (int i = 0; i < op.s_count; i++)
			{
				if (snake[0].x == op.snake[i].x && snake[0].y == op.snake[i].y)
				{
					MessageBox(nullptr, "小绿胜利了 >>_<<", "游戏结束!!", MB_OK);
					exit(0);
				}
			}
	}
	else
	{
		if (snake[0].x <= 0 || snake[0].x >= WIDTH || snake[0].y <= 0 || snake[0].y >= HEIGHT || s_count >= 99)
		{
			MessageBox(nullptr, "小红胜利了 >>_<<", "游戏结束!!", MB_OK);
			exit(0);
		}
		else
			for (int i = 0; i < op.s_count; i++)
			{
				if (snake[0].x == op.snake[i].x && snake[0].y == op.snake[i].y)
				{
					MessageBox(nullptr, "小红胜利了 >>_<<", "游戏结束!!", MB_OK);
					exit(0);
				}
			}
	}
}

猜你喜欢

转载自blog.csdn.net/weixin_42100963/article/details/107449710