easyx图形库基础4:贪吃蛇

贪吃蛇

一实现贪吃蛇:

1.绘制网格:

c 复制代码
#define wide 800
#define high 600

#define Frame 20

//1.绘制边框
void DrawFrame()
{
	setlinecolor(BLACK);
	setlinestyle(PS_SOLID, 1);
	for (int i = 1; i < wide / Frame; i++)
	{
		line(Frame * i, 0, Frame * i, 600);
	}
	for (int i = 1; i < high / Frame; i++)
	{
		line(0, Frame * i,800 , Frame * i);
	}
}

1.绘制蛇:

c 复制代码
int main()
{
	initgraph(wide,high);

	setbkcolor(RGB(188, 227, 245));
	cleardevice();

	//初始化蛇的长度
	int length = 5;
	//初始化蛇的坐标:
	sn snake[5] = { {7,6} ,{6,6}, {5,6},{4,6},{3,6} };
	while (1)
	{
		cleardevice();
		BeginBatchDraw();
		//1.绘制边框
		DrawFrame();
		//2.绘制蛇
		DrawSnake(snake,length);
		FlushBatchDraw();

		Sleep(40);
	}
	EndBatchDraw();
	getchar();
	closegraph();
	return 0;
}
c 复制代码
//2.绘制蛇
void DrawSnake(sn* snake,int length)
{
	setfillcolor(GREEN);
	for (int i = 0; i < length; i++)
	{
		//先绘制头
		int x1 = snake[i].x;
		int y1 = snake[i].y;
		solidrectangle(x1 * Frame, y1 * Frame, (x1 + 1) * Frame, (y1 + 1) * Frame);
	}
}

3.控制蛇的默认移动向右:

c 复制代码
void SnakeMove(sn* snake, int length)
{
	//默认蛇一开始是一直向右移动的;
	sn newsnake = { (snake->x)+1,(snake->y)};
	//2.绘制蛇
	DrawSnake(snake, length);
	FlushBatchDraw();
	


	//进行蛇的移动;
	for (int i = length - 1; i >= 1; i--)
	{
		snake[i] = snake[i - 1];
	}
	snake[0] = newsnake;
}

4.控制蛇的移动方向:

c 复制代码
void SnakeMove(sn* snake, int length,int* vx,int* vy)
{
	//默认蛇一开始是一直向右移动的;
	//2.绘制蛇
	DrawSnake(snake, length);
	FlushBatchDraw();
	//进行蛇的移动;
	if (_kbhit())
	{
		char ch = _getch();
		//蛇是不可以直接走回头路的:
		switch (ch)
		{
			case'A':
			case'a':
				if (*vx == 1 && vy == 0)
					break;
				*vx = -1;
				*vy = 0;
				break;
			case'W':
			case'w':
				if (*vx == 0 && *vy == 1)
					break;
				*vx = 0;
				*vy = -1;
				break;
			case'D':
			case'd':
				if (*vx == -1 && *vy == 0)
					break;
				*vx = 1;
				*vy = 0;
				break;
			case'S':
			case's':
				if (*vx == 0 && *vy == -1)
					break;
				*vx = 0;
				*vy = 1;
				break;
		}
	}
	//控制蛇节点变化
	sn newsnake = { (snake->x)+(*vx) ,(snake->y)+(*vy)};
	for (int i = length - 1; i >= 1; i--)
	{
		snake[i] = snake[i - 1];
	}
	snake[0] = newsnake;
}

5.生成食物

1.食物不可以生成到画布的外面;

2.不可以生成在蛇的身体上面;

3.食物是随机生成的;

c 复制代码
//4.生成食物:
void DrawFeeFood(sn* snake, int length, FD* food)
{		
	int fx = 0;
	int fy = 0;
	int flag = 0;
	while (1)
	{
		//食物坐标的随机生成:
		food->x = rand() % (wide / Frame);
		food->y= rand() % (high / Frame);
		//2.不可以生成在蛇的身体上面,遍历蛇的身体。
		for (int i = 0; i < length; i++)
		{
			if (((food->x) == (snake[i].x)) && ((food->y) == (snake[i].y)))
			{
				flag++;
			}
		}

		if (flag == 0)
		{
			break;
		}
	}
}
c 复制代码
//3.控制蛇的移动
void SnakeMove(sn* snake, int length,FD* food,int* vx,int* vy)
{
	//默认蛇一开始是一直向右移动的;
	//2.绘制蛇
	DrawSnake(snake, length);
	//2.绘制食物:
	if (food->x == 0 && food->y == 0)
	{
		DrawFeeFood(snake, length, food);
	}
	setfillcolor(YELLOW);
	solidrectangle((food->x) * Frame, (food->y) * Frame, (food->x+1) * Frame, (food->y+1) * Frame);
	FlushBatchDraw();
	//进行蛇的移动;
	if (_kbhit())
	{
		char ch = _getch();
		//蛇是不可以直接走回头路的:
		switch (ch)
		{
			case'A':
			case'a':
				if (*vx == 1 && vy == 0)
					break;
				*vx = -1;
				*vy = 0;
				break;
			case'W':
			case'w':
				if (*vx == 0 && *vy == 1)
					break;
				*vx = 0;
				*vy = -1;
				break;
			case'D':
			case'd':
				if (*vx == -1 && *vy == 0)
					break;
				*vx = 1;
				*vy = 0;
				break;
			case'S':
			case's':
				if (*vx == 0 && *vy == -1)
					break;
				*vx = 0;
				*vy = 1;
				break;
		}
	}
	//控制蛇节点变化
	sn newsnake = { (snake->x)+(*vx) ,(snake->y)+(*vy)};
	for (int i = length - 1; i >= 1; i--)
	{
		snake[i] = snake[i - 1];
	}
	snake[0] = newsnake;
}

6.判断蛇吃到食物并且长大。

c 复制代码
//3.控制蛇的移动
void SnakeMove(sn* snake, int* length,FD* food,int* vx,int* vy)
{
	//默认蛇一开始是一直向右移动的;
	//2.绘制蛇
	DrawSnake(snake, *length);
	//3.绘制食物:
	if (food->x == 0 && food->y == 0)
	{
		DrawFeeFood(snake, length, food);
	}
	setfillcolor(YELLOW);
	solidrectangle((food->x) * Frame, (food->y) * Frame, (food->x+1) * Frame, (food->y+1) * Frame);
	FlushBatchDraw();
	//进行蛇的移动;
	if (_kbhit())
	{
		char ch = _getch();
		//蛇是不可以直接走回头路的:
		switch (ch)
		{
			case'A':
			case'a':
				if (*vx == 1 && vy == 0)
					break;
				*vx = -1;
				*vy = 0;
				break;
			case'W':
			case'w':
				if (*vx == 0 && *vy == 1)
					break;
				*vx = 0;
				*vy = -1;
				break;
			case'D':
			case'd':
				if (*vx == -1 && *vy == 0)
					break;
				*vx = 1;
				*vy = 0;
				break;
			case'S':
			case's':
				if (*vx == 0 && *vy == -1)
					break;
				*vx = 0;
				*vy = 1;
				break;
		}
	}
	//控制蛇节点变化
	sn newsnake = { (snake->x)+(*vx) ,(snake->y)+(*vy)};
	for (int i = *length - 1; i >= 1; i--)
	{
		snake[i] = snake[i - 1];
	}
	snake[0] = newsnake;

	//判断蛇是否吃到了食物和生长:
	Grow(snake, length, food);
}
c 复制代码
void Grow(sn* snake, int* length, FD* food)
{
	//保存一下尾的数值
	sn end = snake[(*length) - 1];

	if ((snake[0].x == food->x) && (snake[0].y == food->y))
	{
		//重置食物数值
		food->x = 0;
		food->y = 0;
		//添加尾节点;
		*length = (*length) + 1;
		snake[*length] = end;
	}
}

7.判断游戏结束:

1.蛇头碰到墙壁:

2.蛇头碰到蛇身体:

c 复制代码
//5.判断游戏结束
bool Gameover(sn* snake, int* length)
{
	//1.碰到墙壁
	if ((snake[0].x >= wide / Frame) || (snake[0].x < 0) || (snake[0].y >= high / Frame) || (snake[0].y < 0))
	{
		return true;
	}
	else
	{
		//2.碰到身体
		for (int i = 1; i < (*length); i++)
		{
			if (((snake[0].x)==(snake[i].x))&&((snake[0].y) == (snake[i].y)))
				return true;
		}
	}
	return false;
}

8.重置函数:

c 复制代码
//初始化函数
void initgame(int* length,int* vx,int* vy,sn* snake,FD* food)
{
	//初始化蛇的长度
	*length = 5;
	//初始化蛇的水平初始速度
	*vx = 1;
	*vy = 0;
	//初始化蛇的坐标:
	snake[0] = { 7,6 };
	snake[0] = { 6,6 };
	snake[0] = { 5,6 };
	snake[0] = { 4,6 };
	snake[0] = { 3,6 };
	//初始化食物的坐标;
	*food = { 0,0 };
}

二整体代码:

c 复制代码
#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>
#include<easyx.h>
#include<math.h>
#include<stdbool.h>
#include<conio.h>
#include<time.h>

#define wide 800
#define high 600
#define Frame 20

typedef struct snake {
	int x;
	int y;
}sn;
typedef struct Food {
	int x;
	int y;
}FD;
//1.绘制边框
void DrawFrame()
{
	setlinecolor(BLACK);
	setlinestyle(PS_SOLID, 1);
	for (int i = 1; i < wide / Frame; i++)
	{
		line(Frame * i, 0, Frame * i, 600);
	}
	for (int i = 1; i < high / Frame; i++)
	{
		line(0, Frame * i,800 , Frame * i);
	}
}

//2.绘制蛇
void DrawSnake(sn* snake,int length)
{
	setfillcolor(GREEN);
	for (int i = 0; i < length; i++)
	{
		//先绘制头
		int x1 = snake[i].x;
		int y1 = snake[i].y;
		solidrectangle(x1 * Frame, y1 * Frame, (x1 + 1) * Frame, (y1 + 1) * Frame);
	}
}

//3.生成食物:
void DrawFeeFood(sn* snake, int *length, FD* food)
{		
	int fx = 0;
	int fy = 0;
	int flag = 0;

	while (1)
	{
		//食物坐标的随机生成:
		food->x = rand() % (wide / Frame);
		food->y= rand() % (high / Frame);
		//2.不可以生成在蛇的身体上面,遍历蛇的身体。
		for (int i = 0; i < *length; i++)
		{
			if (((food->x) == (snake[i].x)) && ((food->y) == (snake[i].y)))
			{
				flag++;
			}
		}

		if (flag == 0)
		{
			break;
		}
	}
}

//4判断蛇吃到食物并且长大。
void Grow(sn* snake, int* length, FD* food)
{
	//保存一下尾的数值
	sn end = snake[(*length) - 1];

	if ((snake[0].x == food->x) && (snake[0].y == food->y))
	{
		//重置食物数值
		food->x = 0;
		food->y = 0;
		//添加尾节点;
		*length = (*length) + 1;
		snake[*length] = end;
	}
}

//初始化函数
void initgame(int* length,int* vx,int* vy,sn* snake,FD* food)
{
	//初始化蛇的长度
	*length = 5;
	//初始化蛇的水平初始速度
	*vx = 1;
	*vy = 0;
	//初始化蛇的坐标:
	snake[0] = { 7,6 };
	snake[0] = { 6,6 };
	snake[0] = { 5,6 };
	snake[0] = { 4,6 };
	snake[0] = { 3,6 };
	//初始化食物的坐标;
	*food = { 0,0 };
}
//5.判断游戏结束
bool Gameover(sn* snake, int* length)
{
	//1.碰到墙壁
	if ((snake[0].x >= wide / Frame) || (snake[0].x < 0) || (snake[0].y >= high / Frame) || (snake[0].y < 0))
	{
		return true;
	}
	else
	{
		//2.碰到身体
		for (int i = 1; i < (*length); i++)
		{
			if (((snake[0].x)==(snake[i].x))&&((snake[0].y) == (snake[i].y)))
				return true;
		}
	}
	return false;
}

//6.控制蛇的移动
void SnakeMove(sn* snake, int* length,FD* food,int* vx,int* vy)
{
	//默认蛇一开始是一直向右移动的;
	//2.绘制蛇
	DrawSnake(snake, *length);
	//3.绘制食物:
	if (food->x == 0 && food->y == 0)
	{
		DrawFeeFood(snake, length, food);
	}
	setfillcolor(YELLOW);
	solidrectangle((food->x) * Frame, (food->y) * Frame, (food->x+1) * Frame, (food->y+1) * Frame);
	FlushBatchDraw();
	//进行蛇的移动;
	if (_kbhit())
	{
		char ch = _getch();
		//蛇是不可以直接走回头路的:
		switch (ch)
		{
			case'A':
			case'a':
				if (*vx == 1 && vy == 0)
					break;
				*vx = -1;
				*vy = 0;
				break;
			case'W':
			case'w':
				if (*vx == 0 && *vy == 1)
					break;
				*vx = 0;
				*vy = -1;
				break;
			case'D':
			case'd':
				if (*vx == -1 && *vy == 0)
					break;
				*vx = 1;
				*vy = 0;
				break;
			case'S':
			case's':
				if (*vx == 0 && *vy == -1)
					break;
				*vx = 0;
				*vy = 1;
				break;
		}
	}
	//控制蛇节点变化
	sn newsnake = { (snake->x)+(*vx) ,(snake->y)+(*vy)};
	for (int i = *length - 1; i >= 1; i--)
	{
		snake[i] = snake[i - 1];
	}
	snake[0] = newsnake;

	//判断蛇是否吃到了食物和生长:
	Grow(snake, length, food);
	//判断蛇是否碰到了墙壁和自己
	if (Gameover(snake, length))
	{
		initgame(length, vx, vy, snake, food);
		//Sleep(100);
	}

}

int main()
{
	initgraph(wide,high);
	setbkcolor(RGB(188, 227, 245));
	//获取当前时间作为随机数种子:
	srand((unsigned int)time(NULL));
	cleardevice();

	//初始化蛇的长度
	int length = 5;
	//初始化蛇的水平初始速度
	int vx = 1;
	int vy = 0;
	//初始化蛇的坐标:
	sn snake[100] = { {7,6} ,{6,6}, {5,6},{4,6},{3,6} };
	//初始化食物的坐标;
	FD food = {0,0};


	while (1)
	{
		cleardevice();
		BeginBatchDraw();
		//1.绘制边框
		DrawFrame();
		//2.控制蛇的移动和节点的变化;
		SnakeMove(snake, &length,&food,&vx,&vy);
		Sleep(150);
	}
	EndBatchDraw();
	getchar();
	closegraph();
	return 0;
}
相关推荐
Scott9999HH4 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
腻害兔4 小时前
【若依项目-产品经理视角】深度拆解 RuoYi-Vue-Pro 商城模块:从商品管理到交易引擎,50 张表撑起一整套电商系统
java·大数据·vue.js·产品经理·ai编程
码智社5 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海5 小时前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖6 小时前
JDK 26 新特性详解
java·开发语言
马优晨6 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
人邮异步社区8 小时前
怎么把C语言学到精通?
c语言·开发语言
心平气和量大福大9 小时前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf
ttwuai9 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang
维天说9 小时前
CLI-Switch 2026年3月版历史设计:Hook、TTY 隔离与 JSON 状态
java·服务器·json