【精选】基于EasyX的贪吃蛇小游戏


前言

EasyX Graphics Library 是针对 Visual C++ 的免费绘图库,支持 VC6.0 ~ VC2022,简单易用,学习成本极低,应用领域广泛。目前已有许多大学将 EasyX 应用在教学当中,学习easyX可以提高同学们的编程兴趣,理解简单的页面布局。总之益处多多,本项目是博主在大一上学期学完C++后基于easyX写的一个贪吃蛇小项目。本文会从0到1介绍如何使用easyX开发出一款自己的心仪的小游戏。


一、项目环境

1.Visual Studio 2019

Visual Studio 2019 是历史版本上出色的 Visual Studio。 
可以轻松的集成第三方库。安装教程网上一堆咱就不一一推荐了。

2.EasyX 20200902

点击去easyX官网下载exe文件

操作步骤如下

①点击下载
在这里插入图片描述
②点击More
在这里插入图片描述
③下拉下载稳定版本
在这里插入图片描述
④运行下载的exe文件
在这里插入图片描述
⑤安装自己对应的版本
在这里插入图片描述
⑥结合easyX的文档引入相应的库
在这里插入图片描述

二、运行效果展示

0.加载游戏

在这里插入图片描述

1.主菜单

可以点击四个按钮,进行相应的跳转
在这里插入图片描述

2.游戏设置

可以通过点击按钮调节游戏音乐
在这里插入图片描述

3.游戏说明

游戏的简介

在这里插入图片描述

4.生存模式

生存模式中蛇身触碰自己或者墙壁会死亡,并且不可以反向移动,但是食物不会刷新。

在这里插入图片描述

5.无尽模式

无尽模式中蛇身碰到自己与墙壁不会死亡,可以反向移动,为了提高游戏难度食物每隔5秒会刷新

在这里插入图片描述

三、贪吃蛇关键技术

简单的说一下读者可能会起疑问的地方。

1.引入头文件

#include<graphics.h>
#include<stdlib.h>
#include <time.h>
#include <conio.h>
#include<iostream>
using namespace std;
#pragma comment(lib,"Winmm.lib")

技术支持建议对该库中函数不是很理解的的同学点击前去学习,然后再来看本项目。所有的函数与方法都在链接内。

2.生成食物

代码如下:

使用的是随机数种子,生成两个随机数,然后使用printfood函数画出来
food() {
	srand((unsigned)time(NULL));
	x = rand() % 580 + 30;
	y = rand() % 420 + 30;
	x = x - x % 10;
	y = y - y % 10;
}
void initfood() {
	srand((unsigned)time(NULL));
	x = rand() % 580 + 30;
	y = rand() % 420 + 30;
	x = x - x % 10;
	y = y - y % 10;


}
void printfood() {
	fillrectangle(x - 5, y - 5, x + 5, y + 5);
}

2.菜单页面

代码如下:

//构造函数初始化画布,及音乐资源
mymenu() {
	//画框的大小
	initgraph(640, 480);
	//背景颜色
	setbkcolor(RGB(258, 258, 258));
	//填充颜色
	setfillcolor(RGB(60, 206, 103));
	//线条颜色
	setlinecolor(RGB(0, 0, 0));
	//将游戏音乐加载进来,并对其起别名
	mciSendString(TEXT("open 1.mp3 alias csgo"), NULL, 0, NULL);
	mciSendString(TEXT("open 超级玛丽.mp3 alias super"), NULL, 0, NULL);
	mciSendString(TEXT("open 功夫小子.mp3 alias kongfu"), NULL, 0, NULL);
}

3.蛇身移动【智能键盘】

这里采用的是用一个变量储存蛇身的移动方向,如果没有键键盘的wasd键入
蛇身会一直按照上次键入的asdw其中一个进行移动。
bool judgekb1() {//-------------------------------------判断方向(无尽)
		char ch;
		//这里是智能键盘,判断有无键盘的键入,如果有的话就从缓冲区获取w\a\s\d其中一种
		//然后修改雷类属性,进行智能移动
		if (_kbhit()) {//_kbhit()是判断是否有键盘的键入
			ch = _getch();
			switch (ch) {
			case 'W':
			case 'w':
			case 72:
			{
				direction = 72;
			}break;
			case 'S':
			case 's':
			case 80: {
				direction = 80;
			}break;
			case 'A':
			case 'a':
			case 75: {
				direction = 75;
			}break;
			case 'D':
			case 'd':
			case 77: {
				direction = 77;
			}break;
			case 27: {
				return false;
			}break;
			}
		}
		return true;
	}

四、代码分析

1.食物类

将食物类进行了封装,可以随时生成食物,生成相应对象调用方法。
class food {//----------------------------------食物
private:
	int x;
	int y;
public:
	food() {
		srand((unsigned)time(NULL));
		x = rand() % 580 + 30;
		y = rand() % 420 + 30;
		x = x - x % 10;
		y = y - y % 10;
	}
	void initfood() {
		srand((unsigned)time(NULL));
		x = rand() % 580 + 30;
		y = rand() % 420 + 30;
		x = x - x % 10;
		y = y - y % 10;


	}
	void printfood() {//根据坐标打印食物
		fillrectangle(x - 5, y - 5, x + 5, y + 5);
	}
	int getx() {
		return x;
	}
	int gety() {
		return y;
	}
};

2.蛇身节点类

蛇身的每一个节点,封装起来,可以使用printnode将其画出来
class recsnake {//-----------------------------蛇身
private:
	int x;
	int y;
public:
	//节点初始坐标
	recsnake() {
		x = 320;
		y = 240;
	}
	//拷贝构造函数蛇身节点直接赋值
	recsnake(recsnake& obj) {
		this->x = obj.x;
		this->y = obj.y;
	}
	//重写了赋值运算符
	recsnake& operator = (recsnake& obj) {
		this->x = obj.x;
		this->y = obj.y;
	}
	void setx(int x) {
		this->x = x;
	}
	void sety(int y) {
		this->y = y;
	}
	int getx() {
		return x;
	}
	int gety() {
		return y;
	}
	void printnode() {
		fillrectangle(x - 5, y - 5, x + 5, y + 5);
	}
	~recsnake() {

	}
};

3.蛇身操作类

①类中的属性

int snakeMaxLen;//蛇数组的长度(最大长度,不够了就扩容)
int snakelen;//蛇身长度(记录蛇身有几个节点)
int direction;//方向判断键(蛇身智能移动全靠这个指引)
recsnake* head;//蛇头(实际是一个数组)

②类中的方法

opesnake() {//------------------------------初始化蛇身
	direction = 72;
	snakeMaxLen = 20;
	snakelen = 5;
	int x = 320;
	int y = 240;
	head = new recsnake[snakeMaxLen];
	head[0].setx(x);
	head[0].sety(y);
	for (int i = 0;i < 5;i++) {
		x += 10;
		head[i].setx(x);
		head[i].sety(y);
	}
}
void rebuildsnake() {//------重建蛇身数组(蛇死掉或者重新开始了)

}
void EatFood_snake() {//----------------蛇身数组扩容(蛇吃的太大了)
	
}
~opesnake() {//释放数组
	delete[] head;
}
//方便操作每一个节点
recsnake operator[](int i) {
	return head[i];
}
void setlen(int len) {//设置蛇身长度
	snakelen = len;
}
int getlen() {//获取蛇身长度
	return snakelen;
}
recsnake*& gethand() {//获取蛇身头部
	return head;
}
void printlink() {//蛇头的移动
}
bool judgekb1() {//-------------------------------------判断方向(无尽)
}
bool judgekb2() {//-------------------------------------判断方向(生存)
}
void movesnake() {//蛇身的移动
}
bool judgedie() {//判断死亡
}
void judgewall() {//判断蛇头是否撞墙,蛇头不先撞墙其他的也不会撞墙
}
bool judgefood(int x, int y) {//判断是否撞食物
}
bool snakeeatfood(int x, int y) {//吃了食物长在哪里
}

4.菜单类

①类中属性

//菜单用到的背景图
IMAGE mage;
IMAGE twomage;
IMAGE treemage;
IMAGE foremage;

②类中方法

	mymenu() {//初始化画布还有音乐
	}
	void initcartoon() {//进入游戏初始化动画
	}
	void closecartoon() {//退出游戏初始化动画
	}
	bool mainmenu() {//主菜单会根据鼠标的点击事件进行响应的操作
					 //各个页面形成了闭环,只有点击退出或者×号才可以退出
	}

	~mymenu() {
		closegraph();
	}

五、源码与项目素材

源代码

#include<graphics.h>
#include<stdlib.h>
#include <time.h>
#include <conio.h>
#include<iostream>
using namespace std;
#pragma comment(lib,"Winmm.lib")
static int musick=0;//k有0123--0静音--1音乐1--2音乐2....
class food {//----------------------------------食物
private:
	int x;
	int y;
public:
	food() {
		srand((unsigned)time(NULL));
		x = rand() % 580 + 30;
		y = rand() % 420 + 30;
		x = x - x % 10;
		y = y - y % 10;
	}
	void initfood() {
		srand((unsigned)time(NULL));
		x = rand() % 580 + 30;
		y = rand() % 420 + 30;
		x = x - x % 10;
		y = y - y % 10;


	}
	void printfood() {
		fillrectangle(x - 5, y - 5, x + 5, y + 5);
	}
	int getx() {
		return x;
	}
	int gety() {
		return y;
	}
};
class recsnake {//-----------------------------蛇身
private:
	int x;
	int y;
public:
	recsnake() {
		x = 320;
		y = 240;
	}
	recsnake(recsnake& obj) {
		this->x = obj.x;
		this->y = obj.y;
	}
	recsnake& operator = (recsnake& obj) {
		this->x = obj.x;
		this->y = obj.y;
	}
	void setx(int x) {
		this->x = x;
	}
	void sety(int y) {
		this->y = y;
	}
	int getx() {
		return x;
	}
	int gety() {
		return y;
	}
	void printnode() {
		fillrectangle(x - 5, y - 5, x + 5, y + 5);
	}
	~recsnake() {

	}
};
class opesnake {
private:
	int snakeMaxLen;//蛇数组的长度
	int snakelen;//蛇身长度
	int direction;//方向判断键
	recsnake* head;//蛇头
public:
	opesnake() {//------------------------------初始化蛇身
		direction = 72;
		snakeMaxLen = 20;
		snakelen = 5;
		int x = 320;
		int y = 240;
		head = new recsnake[snakeMaxLen];
		head[0].setx(x);
		head[0].sety(y);
		for (int i = 0;i < 5;i++) {
			x += 10;
			head[i].setx(x);
			head[i].sety(y);
		}
	}
	void rebuildsnake() {//------重建蛇身数组(蛇死掉或者重新开始了)
		delete[] head;
		direction = 72;
		snakeMaxLen = 20;
		snakelen = 5;
		int x = 320;
		int y = 240;
		head = new recsnake[snakeMaxLen];
		head[0].setx(x);
		head[0].sety(y);
		for (int i = 0;i < 5;i++) {
			x += 10;
			head[i].setx(x);
			head[i].sety(y);
		}
	}
	void EatFood_snake() {//----------------蛇身数组扩容(蛇吃的太大了)
		recsnake* p;
		p = new recsnake[snakeMaxLen + 10];
		snakeMaxLen += 10;
		for (int i=0;i < snakelen;i++) {
			p[i].setx(head[i].getx());
			p[i].sety(head[i].gety());
		}
		delete[] head;
		head = p;
		return;
	}
	~opesnake() {
		delete[] head;
	}
	recsnake operator[](int i) {
		return head[i];
	}
	void setlen(int len) {
		snakelen = len;
	}
	int getlen() {
		return snakelen;
	}
	recsnake*& gethand() {
		return head;
	}
	void printlink() {//蛇头的移动
		for (int i = 0;i < snakelen;i++) {
			head[i].printnode();
			if (i == 0) {
				if (direction == 72) {
					fillcircle(head[0].getx() + 5, head[0].gety() - 5, 3);
					fillcircle(head[0].getx() - 5, head[0].gety() - 5, 3);
				}
				else if (direction == 80) {
					fillcircle(head[0].getx() + 5, head[0].gety() + 5, 3);
					fillcircle(head[0].getx() - 5, head[0].gety() + 5, 3);
				}
				else if (direction == 75) {
					fillcircle(head[0].getx() - 5, head[0].gety() + 5, 3);
					fillcircle(head[0].getx() - 5, head[0].gety() - 5, 3);
				}
				else if (direction == 77) {
					fillcircle(head[0].getx() + 5, head[0].gety() + 5, 3);
					fillcircle(head[0].getx() + 5, head[0].gety() - 5, 3);
				}
			}
		}
		//cout << snakelen<<endl;
	}
	bool judgekb1() {//-------------------------------------判断方向(无尽)
		char ch;
		if (_kbhit()) {
			ch = _getch();
			switch (ch) {
			case 'W':
			case 'w':
			case 72:
			{
				direction = 72;
			}break;
			case 'S':
			case 's':
			case 80: {
				direction = 80;
			}break;
			case 'A':
			case 'a':
			case 75: {
				direction = 75;
			}break;
			case 'D':
			case 'd':
			case 77: {
				direction = 77;
			}break;
			case 27: {
				return false;
			}break;
			}
		}
		return true;
	}
	bool judgekb2() {//-------------------------------------判断方向(生存)
		char ch;
		if (_kbhit()) {
			ch = _getch();
			switch (ch) {
			case 'W':
			case 'w':
			case 72:
			{
				if (direction != 80) {
					direction = 72;
				}
			}break;
			case 'S':
			case 's':
			case 80: {
				if (direction != 72) {
					direction = 80;
				}
			}break;
			case 'A':
			case 'a':
			case 75: {
				if (direction != 77) {
					direction = 75;
				}
			}break;
			case 'D':
			case 'd':
			case 77: {
				if (direction != 75) {
					direction = 77;
				}
			}break;
			case 27: {
				return false;
			}break;
			}
		}
		return true;
	}
	void movesnake() {
		int x[100], i;
		int y[100];
		x[0] = head->getx();
		y[0] = head->gety();
		switch (direction) {
		case 72:
		{
			head->sety(head->gety() - 10);
		}
		break;
		case 80:
		{
			head->sety(head->gety() + 10);
		}
		break;
		case 75:
		{
			head->setx(head->getx() - 10);
		}
		break;
		case 77:
		{
			head->setx(head->getx() + 10);
		}
		break;
		}
		for (i = 0;i < snakelen;i++) {
			if (i + 1 < snakelen) {
				x[i + 1] = head[i + 1].getx();
				y[i + 1] = head[i + 1].gety();
				head[i + 1].setx(x[i]);
				head[i + 1].sety(y[i]);
			}
		}
		//i = 1;
	}
	bool judgedie() {
		if (head[0].gety() == 20 || head[0].gety() == 460 || head[0].getx() == 20 || head[0].getx() == 620) {
			//outtextxy(200, 240, L"很遗憾,您撞墙而死!将要退出!");
			return false;
		}
		for (int i = 1;i < snakelen;i++) {
			if (head[0].getx() == head[i].getx() && head[0].gety() == head[i].gety()) {
				//outtextxy(200, 240, L"很遗憾,您咬到了自己,将要退出!");
				return false;
			}
		}
		return true;
	}
	void judgewall() {
		if (head[0].gety() == 20 || head[0].gety() == 460 || head[0].getx() == 20 || head[0].getx() == 620) {
			if (head[0].gety() == 20) {
				head[0].sety(460);
			}
			else if (head[0].gety() == 460) {
				head[0].sety(20);
			}
			else if (head[0].getx() == 20) {
				head[0].setx(620);
			}
			else if (head[0].getx() == 620) {
				head[0].setx(20);
			}
		}
	}
	bool judgefood(int x, int y) {
		for (int i = 0;i < snakelen;i++) {
			if (head[i].getx() == x && head[i].gety() == y) {
				return false;
			}
		}
		return true;
	}
	bool snakeeatfood(int x, int y) {
		if (head[0].getx() == x && head[0].gety() == y) {
			snakelen++;
			switch (direction) {
			case 72:
			{
				head[snakelen].setx(head[snakelen - 1].getx());
				head[snakelen].sety(head[snakelen - 1].gety() + 10);
			}
			break;
			case 80:
			{
				head[snakelen].setx(head[snakelen - 1].getx());
				head[snakelen].sety(head[snakelen - 1].gety() - 10);
			}
			break;
			case 75:
			{
				head[snakelen].setx(head[snakelen - 1].getx() + 10);
				head[snakelen].sety(head[snakelen - 1].gety());
			}
			break;
			case 77:
			{
				head[snakelen].setx(head[snakelen - 1].getx() - 10);
				head[snakelen].sety(head[snakelen - 1].gety());
			}
			break;
			}
			return true;
		}
		return false;
	}
};
class mymenu {
private:
	IMAGE mage;
	IMAGE twomage;
	IMAGE treemage;
	IMAGE foremage;
public:
	mymenu() {
		initgraph(640, 480);
		setbkcolor(RGB(258, 258, 258));
		setfillcolor(RGB(60, 206, 103));
		setlinecolor(RGB(0, 0, 0));
		mciSendString(TEXT("open 1.mp3 alias csgo"), NULL, 0, NULL);
		mciSendString(TEXT("open 超级玛丽.mp3 alias super"), NULL, 0, NULL);
		mciSendString(TEXT("open 功夫小子.mp3 alias kongfu"), NULL, 0, NULL);
	}
	void initcartoon() {
		cleardevice();
		outtextxy(240, 250, L"Loinding");
		for (int i = 300;i < 360;i += 20) {
			outtextxy(i, 250, L". ");
			Sleep(1000);
		}
	}
	void closecartoon() {
		cleardevice();
		outtextxy(200, 230, L"正在退出游戏,欢迎下次再来");
		outtextxy(240, 250, L"Loind");
		for (int i = 290;i < 360;i += 20) {
			outtextxy(i, 250, L". ");
			Sleep(1000);

		}
	}
	bool mainmenu() {
		MOUSEMSG m;
Heremenu:
		cleardevice();
		loadimage(&mage, L"2.GIF", 640, 480);
		loadimage(&foremage, L"5.PNG", 150, 150);
		putimage(0, 0, &mage);
		setfillcolor(RED);
		fillrectangle(265, 295, 345, 320);fillrectangle(355, 295, 435, 320);
		fillrectangle(265, 335, 345, 360);fillrectangle(355, 335, 435, 360);
		settextstyle(16, 8, _T("Courier"));	// 设置字体
		setbkmode(TRANSPARENT);
		outtextxy(270, 300, L"开始游戏");outtextxy(360, 300, L"游戏设置");
		outtextxy(270, 340, L"游戏说明");outtextxy(360, 340, L"退出游戏");
		outtextxy(100, 460, L"说明:游戏内点击ESC,返回主菜单,WSAD,分别为上下左右移动");
		while (1) {
			m = GetMouseMsg();
			//---------------开始游戏
			if (m.x >= 265 && m.x <= 345 && m.y >= 295 && m.y <= 320) {
				setlinecolor(BLUE);
				rectangle(260, 290, 349, 325);
				if (m.uMsg == WM_LBUTTONDOWN) {
					return true;
				}
			}
			else {
				setlinecolor(BLACK);
				rectangle(260, 290, 349, 325);
			}
			//-------------游戏说明
			if (m.x >= 265 && m.x <= 345 && m.y >= 335 && m.y <= 360) {
				setlinecolor(BLUE);
				rectangle(260, 330, 349, 365);
				if (m.uMsg == WM_LBUTTONDOWN) {
					cleardevice();
					putimage( 490, 0,&foremage);
					outtextxy(370, 0, L"如果玩累了");
					outtextxy(370, 30, L"打赏一下作者吧");
					outtextxy(0, 50, L"在很久很久以前.....诸神的黄昏......");
					outtextxy(0, 100, L"不远处的天空一声巨响,混沌之中,有一群社会青年排成长长的一队");
					outtextxy(0, 150, L"他们穿着同样颜色的衣服,有着相同的特征,只有站在首位的青年比较独特");
					outtextxy(0, 200, L"他头顶诛杀帽,带领大队誓要将所有落单的青年集结起来");
					outtextxy(0, 250, L"然后做一件有意义的事情........");
					outtextxy(0, 300, L"游戏分为两种模式,并且出现的几率相同");
					outtextxy(0, 350, L"无尽模式,每位青年互相认识,并且可以穿越时空,是一个打不死的小虫");
					outtextxy(0, 400, L"生存模式,要处处小心^_^");
					fillrectangle(565, 450, 635, 475);
					outtextxy(570, 455, L"明白了");
					while (1) {
						m = GetMouseMsg();
					if (m.x >= 565 && m.x <= 635 && m.y >= 450 && m.y <= 475) {
						setlinecolor(BLUE);
						rectangle(560, 445, 640, 480);
						if (m.uMsg == WM_LBUTTONDOWN) {
							goto Heremenu;
						}
					}
					else {
						setlinecolor(BLACK);
						rectangle(560, 445, 640, 480);
					}
					}
				}
			}
			else {
				setlinecolor(BLACK);
				rectangle(260, 330, 349, 365);
			}
			//--------------游戏设置
			if (m.x >= 335 && m.x <= 435 && m.y >= 295 && m.y <= 320) {
				setlinecolor(BLUE);
				rectangle(350, 290, 440, 325);
				if (m.uMsg == WM_LBUTTONDOWN) {
				Heremusic:			
					//BeginBatchDraw();
					loadimage(&treemage, L"3.JPG", 640, 480);
					putimage(0,0,&treemage);
					settextstyle(40, 16, _T("楷体"));	// 设置字体
					if (musick == 0) {
						mciSendString(TEXT("stop csgo"), NULL, 0, NULL);
						mciSendString(TEXT("stop kongfu"), NULL, 0, NULL);
						mciSendString(TEXT("stop super"), NULL, 0, NULL);
						outtextxy(420, 100, L"静音");
					}
					else if (musick == 1) {
						mciSendString(TEXT("stop csgo"), NULL, 0, NULL);
						mciSendString(TEXT("stop super"), NULL, 0, NULL);
						mciSendString(TEXT("play kongfu"), NULL, 0, NULL);
						outtextxy(400, 100, L"模式一");
					}
					else if (musick == 2) {
						mciSendString(TEXT("stop kongfu"), NULL, 0, NULL);
						mciSendString(TEXT("stop csgo"), NULL, 0, NULL);
						mciSendString(TEXT("play super"), NULL, 0, NULL);
						outtextxy(400, 100, L"模式二");//-----这个坐标可以
					}
					else if (musick == 3) {
						mciSendString(TEXT("stop kongfu"), NULL, 0, NULL);
						mciSendString(TEXT("stop super"), NULL, 0, NULL);
						mciSendString(TEXT("play csgo"), NULL, 0, NULL);
						outtextxy(400, 100, L"模式三");
					}
					fillrectangle(565, 450, 635, 475);
					fillrectangle(90, 90, 240, 150);
					outtextxy(100, 100, L"声音模式");
					fillrectangle(365, 107, 385, 127);
					fillrectangle(515, 107, 535, 127);
					settextstyle(16, 8, _T("Courier"));	// 设置回原来的字体
					outtextxy(570, 455, L"设置完毕");
					outtextxy(370, 70, L"点击按钮以切换模式");
					while (1) {
						m = GetMouseMsg();//-------退出设置按钮
						if (m.x >= 565 && m.x <= 635 && m.y >= 450 && m.y <= 475) {
							setlinecolor(BLUE);
							rectangle(560, 445, 640, 480);
							if (m.uMsg == WM_LBUTTONDOWN) {
								goto Heremenu;
							}
						}
						else {
							setlinecolor(BLACK);
							rectangle(560, 445, 640, 480);
						}
						if (m.x >= 365 && m.x <= 385 && m.y >= 107 && m.y <= 127) {//---声音模式按钮1
							setlinecolor(BLUE);
							rectangle(360, 102, 390, 132);
							if (m.uMsg == WM_LBUTTONDOWN) {
								if (musick == 0) {
									musick = 3;
								}
								else if (musick == 1) {
									musick = 0;
								}
								else if (musick == 2) {
									musick = 1;
								}
								else if (musick == 3) {
									musick = 2;
								}
								cleardevice();
								//EndBatchDraw();
								goto Heremusic;
							}
						}
						else {
							setlinecolor(BLACK);
							rectangle(360, 102, 390, 132);
						}
						if (m.x >= 515 && m.x <= 535 && m.y >= 107 && m.y <= 127) {//---声音模式按钮1
							setlinecolor(BLUE);
							rectangle(510, 102, 540, 132);
							if (m.uMsg == WM_LBUTTONDOWN) {
								if (musick == 0) {
									musick = 1;
								}
								else if (musick == 1) {
									musick = 2;
								}
								else if (musick == 2) {
									musick = 3;
								}
								else if (musick == 3) {
									musick = 0;
								}
								cleardevice();
								goto Heremusic;
							}
						}
						else {
							setlinecolor(BLACK);
							rectangle(510, 102, 540, 132);
						}
					}
				}
			}
			else {
				setlinecolor(BLACK);
				rectangle(350, 290, 440, 325);
			}
			//-----------------------------退出游戏
			if (m.x >= 335 && m.x <= 435 && m.y >= 335 && m.y <= 360) {
				setlinecolor(BLUE);
				rectangle(350, 330, 440, 365);
				if (m.uMsg == WM_LBUTTONDOWN) {
					return false;
				}
			}
			else {
				setlinecolor(BLACK);
				rectangle(350, 330, 440, 365);
			}
		}
	}
	void mainmap() {
		loadimage(&twomage, L"1.JPG", 640, 480);
		putimage(0, 0, &twomage);
		srand((unsigned)time(NULL));
		for (int i = 10;i < 640;i += 20) {
			if (i == 10) {
				setfillcolor(RGB(rand() % 258, rand() % 258, rand() % 258));
				for (int j = 10;j < 480;j += 20) {
					fillrectangle(i - 10, j - 10, i + 10, j + 10);
				}
			}
			else if (i == 630) {
				for (int j = 10;j < 480;j += 20) {
					fillrectangle(i - 10, j - 10, i + 10, j + 10);
				}
			}
			else {
				fillrectangle(i - 10, 0, i + 10, 20);
				fillrectangle(i - 10, 460, i + 10, 480);
			}
		}
		setfillcolor(RGB(60, 206, 103));
	}
	~mymenu() {
		closegraph();
	}
};
int main() {
	opesnake myrecsnake;
	mymenu mainmenu;
	food myfood;
	bool k = true, foodk = true, menuk = true, judgekbk = true,eatk=false;
	//mainmenu.initcartoon();//--------------------刚进入游戏的动画效果
Here:
	menuk = mainmenu.mainmenu();
	if (menuk == true) {
		srand((unsigned)time(NULL));//-----------------随机进入1,2模式
		int yyy = rand() % 2;
		if (yyy == 0) {
		cleardevice();
		settextstyle(40, 16, _T("Courier"));
		outtextxy(240, 220, L"生存模式");
		settextstyle(16, 8, _T("Courier"));
		Sleep(1500);
		cleardevice();
		while (1) {
			while (1) {//---------------------生成食物,直到食物不在蛇身上才跳出循环	
				BeginBatchDraw();//---------------批量绘图函数
				foodk = myrecsnake.judgefood(myfood.getx(), myfood.gety());
				if (foodk == true) {//生成食物不在蛇身上成功的话break,否则重新生成
					break;
				}
				else {
					myfood.initfood();
				}
			}
			cleardevice();
			mainmenu.mainmap();//-----------------------画地图边框
			myfood.printfood();//-----------------------打印食物
			judgekbk = myrecsnake.judgekb2();//-------------判断有没有键盘的输入
			if (judgekbk == false) {
				myrecsnake.rebuildsnake();//----------------重建蛇身
				EndBatchDraw();
				cleardevice();
				goto Here;
			}
			myrecsnake.movesnake();//----------------------根据方向键移动蛇身
			myrecsnake.printlink();//----------------------将蛇身打印出来
			k = myrecsnake.judgedie();//-------------------判断有没有撞墙
			if (k == false) {
				myrecsnake.rebuildsnake();
				k = true;
				EndBatchDraw();
				settextstyle(40, 16, _T("Courier"));
				outtextxy(200, 240, L"很遗憾,您不幸阵亡");
				settextstyle(16, 8, _T("Courier"));	
				Sleep(1500);
				cleardevice();
				goto Here;
			}

			myrecsnake.snakeeatfood(myfood.getx(), myfood.gety());//-------------判断吃到了食物
			EndBatchDraw();
			Sleep(100);
		}
		}
		else if (yyy == 1) {
			cleardevice();
			settextstyle(40, 16, _T("Courier"));
			outtextxy(240, 220, L"无尽模式");
			settextstyle(16, 8, _T("Courier"));
			Sleep(1500);
			cleardevice();
			int foodi=0;
			while (1) {
				BeginBatchDraw();
				foodi++;
				if (foodi == 30||eatk==true) {
				myfood.initfood();
				foodi = 0;
				eatk = false;
				}
				cleardevice();
				mainmenu.mainmap();
				myfood.printfood();
				judgekbk = myrecsnake.judgekb1();
				if (judgekbk == false) {
					myrecsnake.rebuildsnake();
					EndBatchDraw();
					cleardevice();
					goto Here;
				}
				myrecsnake.movesnake();
				myrecsnake.printlink();
				myrecsnake.judgewall();
				eatk=myrecsnake.snakeeatfood(myfood.getx(), myfood.gety());
				EndBatchDraw();
				Sleep(100);
			}
			foodi = 0;
		}
	}
	else if (menuk == false) {
	//	mainmenu.closecartoon();//--------------退出游戏的动画效果
		exit(0);
	}
	return 0;
}

项目素材

在这里插入图片描述
游戏背景图
请添加图片描述
主菜单
请添加图片描述
设置菜单
请添加图片描述

还有几个音乐不知怎么上传,感兴趣的小伙伴私聊我来拿吧。


总结

本项目的两种模式选择是自动的,有50%几率进入无尽模式,有50%几率进入生存模式,看大家运气。easyX图像库操作简单,是开发游戏之路上一个很好的入门技术。希望本博客对大家有一定的作用。如有问题请评论区及时联系博主。
在这里插入图片描述

关注冲哥不迷路!(^_−)☆

  • 32
    点赞
  • 126
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

酷尔。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值