总看别人写贪吃蛇,自己也来写一个吧

news2024/11/23 17:04:52

贪吃蛇是一个流行度非常高的游戏,玩法十分简单,从最初的方块机上就有这个游戏了,后来出现的手机中也是加入了这个游戏,无聊的时候可以打发时间玩一会。这个游戏可谓是非常的简单,容易上手,所以直到现在,还能看到它的身影。大多数学习编程的同学在学习编程语言后,也都会想着写一个自己的游戏,可能大部分同学也是抱着这样的想法开始学习的编程,那么简单的贪吃蛇游戏就成了很好的练手项目,所以可以在网上看到很多各种编程语言的贪吃蛇游戏代码。

每当看到网上这些贪吃蛇代码的时候,就觉得也不是很难,逻辑也简单,看看就会了,所以也没有实际动手去编写一下(不知道有没有人和我一样)。可是每当有时间的时候,看一些练手项目的时候大概率会看到贪吃蛇这个游戏,然后就会看到各路大神编写的代码,有100多行完成的,有200多行完成的,还有14行就完成的,就感觉挺厉害的。这个时候我就在想,我自己写这个游戏的话,需要多少行代码能够完成呢?反正14行我是搞不定的,估计200行左右还是可能的。正好最近时间上比较闲,所以就动手来写一下,也不要总看不练。

代码是使用C++进行编写的,图形界面绘制选择的是EasyX。EasyX Graphics Library 是针对 Visual C++ 的免费绘图库,支持 VC6.0 ~ VC2022,简单易用,官网地址是:EasyX Graphics Library for C++,有兴趣的同学可以去看一下。至于需求逻辑方面就没有什么好说的了。那么接下来,直接上代码。

#include <graphics.h>
#include <time.h>
#include <conio.h>

#include <vector>
#include <array>

#define WIN_SIZE 600
#define BLOCK_SIZE 40
#define SPEED 100
#define LEN (WIN_SIZE / BLOCK_SIZE)

// 声明节点结构体,用于表示蛇身体和食物的坐标
struct Node
{
	int x;
	int y;
};

// 声明方向
enum Direction
{
	UP, DOWN, LEFT, RIGHT
};

// 声明数组值类型
enum BlockType
{
	// 0:空白,1:蛇身,2:食物
	NONE = 0, SNAKE, FOOD
};

// 绘制指定节点并设置所在二维数组
void drawNode(const Node& node, std::array<std::array<UINT8, LEN>, LEN>& arr,
	BlockType type = SNAKE)
{
	setfillcolor(RED);
	fillrectangle(node.x * BLOCK_SIZE, node.y * BLOCK_SIZE,
		node.x * BLOCK_SIZE + BLOCK_SIZE, node.y * BLOCK_SIZE + BLOCK_SIZE);
	arr[node.y][node.x] = type;
}

// 清除指定节点并清除二维数组对应数据
void clearNode(const Node& node, std::array<std::array<UINT8, LEN>, LEN>& arr)
{
	setfillcolor(WHITE);
	fillrectangle(node.x * BLOCK_SIZE, node.y * BLOCK_SIZE,
		node.x * BLOCK_SIZE + BLOCK_SIZE, node.y * BLOCK_SIZE + BLOCK_SIZE);
	arr[node.y][node.x] = NONE;
}

// 绘制界面方格
void drawBlock()
{
	setbkcolor(WHITE);
	setlinecolor(GREEN);
	cleardevice();

	for (int i = BLOCK_SIZE; i <= WIN_SIZE; i += BLOCK_SIZE)
	{
		line(i, 0, i, WIN_SIZE);
		line(0, i, WIN_SIZE, i);
	}
}

// 绘制蛇身并设置蛇身所在二维数组
void drawSnake(const std::vector<Node>& snake, std::array<std::array<UINT8, LEN>, LEN>& arr)
{
	for (Node node : snake)
	{
		drawNode(node, arr);
	}
}

// 随机生成食物
void randFood(std::array<std::array<UINT8, LEN>, LEN>& arr)
{
	int x, y;
	do
	{
		x = rand() % LEN;
		y = rand() % LEN;
	} while (arr[y][x] == SNAKE);
	drawNode({x, y}, arr, FOOD);
}

// 移动,如果碰到蛇身或墙壁则游戏结束
bool move(std::vector<Node>& snake, std::array<std::array<UINT8, LEN>, LEN>& arr,
	Direction& direction)
{
	Node first = snake.back();
	Node second = snake.at(snake.size() - 2);
	Node node = first;
	switch (direction)
	{
	case UP:
		node.y--;
		break;
	case DOWN:
		node.y++;
		break;
	case LEFT:
		node.x--;
		break;
	case RIGHT:
		node.x++;
		break;
	}
	// 判断是否可以移动,移动方向不能为当前方向的反方向
	if (!((node.x == second.x && (direction == LEFT || direction == RIGHT)) ||
		(node.y == second.y && (direction == UP || direction == DOWN))))
	{
		if (node.x < 0 || node.x >= LEN ||
			node.y < 0 || node.y >= LEN ||
			arr[node.y][node.x] == SNAKE)
		{
			// 装到墙壁或蛇身则游戏结束
			return false;
		}
		else if (arr[node.y][node.x] == FOOD)
		{
			arr[node.y][node.x] == SNAKE;
			snake.push_back(node);
			randFood(arr);
		}
		else
		{
			arr[node.y][node.x] == SNAKE;
			snake.push_back(node);
			clearNode(snake.front(), arr);
			snake.erase(snake.begin());
			drawNode(node, arr);
		}
	}

	return true;
}

// 游戏
void game()
{
	using namespace std;

	// 蛇身
	vector<Node> snake = { {0, 0}, {1, 0}, {2, 0} };
	// 二维数组,记录蛇身和食物是否在某位置上
	array<array<UINT8, LEN>, LEN> arr;
	for (auto& ar : arr) {
		memset(&ar, NONE, size(ar));
	}
	// 默认起始向右移动
	Direction direction = RIGHT;

	drawBlock();
	drawSnake(snake, arr);

	randFood(arr);

	// 定义消息变量
	ExMessage m;
	while (move(snake, arr, direction))
	{
		// 获取一条按键消息
		peekmessage(&m, EX_KEY);
		switch (m.vkcode)
		{
		case VK_UP:
			direction = direction == DOWN ? DOWN : UP;
			break;
		case VK_DOWN:
			direction = direction == UP ? UP : DOWN;
			break;
		case VK_LEFT:
			direction = direction == RIGHT ? RIGHT : LEFT;
			break;
		case VK_RIGHT:
			direction = direction == LEFT ? LEFT : RIGHT;
			break;
		}

		Sleep(150);
	}

	settextstyle(36, 0, _T("Consolas"));
	settextcolor(RED);
	outtextxy(100, 250, "GAME OVER,按s键开始游戏");
}

int main()
{
	// 创建绘图窗口
	initgraph(WIN_SIZE, WIN_SIZE);
	// 设置随机种子
	srand((unsigned)time(NULL));

	while (true)
	{
		game();
		while ('s' != _getch());
	}

	closegraph();
	return 0;
}

代码量和我开始预计的差不多,200行出头,程序应该还有可以优化的地方。这里贴出代码是为了给大家提供一个思路,有兴趣的也可以自己尝试着写一写这个贪吃蛇,看看用多少行代码可以完成,也是对自己编程能力的锻炼。最后,让我们看一下编写的这个贪吃蛇的运行效果。

欢迎关注我的公众号

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2211446.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

番外篇 | 常用的激活函数汇总 | 20+种激活函数介绍及其公式、图像等

前言:Hello大家好,我是小哥谈。激活函数(Activation Function)是神经网络中的一种重要概念,用于控制神经网络中神经元的激活方式。在传统的神经网络中,激活函数被用来将神经元的输出从数值转换为可以被神经网络其他部分理解的非数值形式。激活函数通常被定义为神经元的输…

电能表预付费系统-标准传输规范(STS)(2)

5. 标准传输规格参考模型 5.1 一般付费电表功能参考图 In a single-device payment meter all the essential functions are located in a single enclosure as depicted in Figure 1 above, while in a multi-device payment meter it is possible for the TokenCarrierToMe…

Pagehelper获取total错误

前言 在使用若依框架的pagehelper时&#xff0c;给分页表设置数据的时候前端只收到了分页的那一页的数据&#xff0c;总记录数不符合要求 我想要的效果如下&#xff0c;可以实现分页&#xff0c;和显示总记录数 但是实际情况为 但是我的数据库有11条记录&#xff0c;他这里明…

【python学习】1-2 配置python系统环境变量

1.点击“我的电脑”右键&#xff0c;点击属性&#xff0c;点击“高级系统设置”&#xff0c;再点击环境变量。 2.选择“系统变量”中的Path后&#xff0c;点击编辑。 3.点击新建&#xff0c;添加如图两个路径&#xff0c;即是python安装的路径位置后&#xff0c;点击确定。

前端脚手架插件安装总结(axios,element-ui,bootstrap,echarts等)

1.打开前端项目终端 输入命令 vue ui 进入图形化界面 a.选择插件 b.选择添加插件 c.安装插件 d.完成安装

手写mybatis之完善ORM框架,增删改查操作

前言 目前这个框架中所提供的 SQL 处理仅有一个 select 查询操作&#xff0c;还没有其他我们日常常用的 insert、update、delete&#xff0c;以及 select 查询返回的集合类型数据。 其实这一部分新增处理 SQL 的内容&#xff0c;也就是在 SqlSession 需要定义新的接口&#xff…

Java 读取word , 作为私有知识库做RAG答疑

检索与生成的技术&#xff08;RAG)&#xff0c;可以提升文本精准度与企业数据相关性 检索增强生成 (RAG) 是一种技术&#xff0c;它结合了检索模型和生成模型&#xff0c;旨在通过私有或专有的数据源来辅助文本生成。在使用大模型时&#xff0c;一个常见问题是模型可能会产生“…

利用Spring Boot优化企业知识管理

1系统概述 1.1 研究背景 如今互联网高速发展&#xff0c;网络遍布全球&#xff0c;通过互联网发布的消息能快而方便的传播到世界每个角落&#xff0c;并且互联网上能传播的信息也很广&#xff0c;比如文字、图片、声音、视频等。从而&#xff0c;这种种好处使得互联网成了信息传…

【Java SE】数组的应用

&#x1f525;博客主页&#x1f525;&#xff1a;【 坊钰_CSDN博客 】 欢迎各位点赞&#x1f44d;评论✍收藏⭐ 目录 1. 数组的概念 1.1 为什么存在数组 1.2 数组是什么 1.3 数组的创建 1.4 数组的初始化 1.4.1 动态初始化 1.4.2 静态初始化 1.4.3 默认值 1.5 数组的使…

【最新华为OD机试E卷-支持在线评测】英文输入法(100分)多语言题解-(Python/C/JavaScript/Java/Cpp)

🍭 大家好这里是春秋招笔试突围 ,一枚热爱算法的程序员 💻 ACM金牌🏅️团队 | 大厂实习经历 | 多年算法竞赛经历 ✨ 本系列打算持续跟新华为OD-E/D卷的多语言AC题解 🧩 大部分包含 Python / C / Javascript / Java / Cpp 多语言代码 👏 感谢大家的订阅➕ 和 喜欢�…

AD之Layout设计规则

设计规则&#xff1a; 间距 线宽 过孔 铺铜 其他 1.添加类 这里建立了PWR类&#xff0c;与电源相关的网络 2.间距规则:6mil的成本低 3.线宽规则&#xff1a;PWR的优先级排第一&#xff0c;否则不起作用 4.过孔规则&#xff1a;8mil<大小<12mil 4.铺铜规则

音视频开发:FFmpeg库的使用

文章目录 一、FFmpeg的介绍二、FFmpeg的安装三、FFmpeg的使用1.ffplay&#xff1a;播放音视频2.ffprobe&#xff1a;查看视频信息3.ffmpeg&#xff1a;处理视频(1)格式转换(2)帮助 四、参考资料 一、FFmpeg的介绍 FFmpeg 是使用广泛的多媒体框架&#xff0c;是一个强大的音视频…

LeetCode讲解篇之740. 删除并获得点数

文章目录 题目描述题解思路题解代码题解链接 题目描述 题解思路 首先对于这题我们如果将所有点数装入一个切片f中&#xff0c;该切片f中的i号下标表示所有点数为i的点数之和 那么这题就转换成了打家劫舍这道题&#xff0c;也就是求选择了切片中某个下标的元素后&#xff0c;该…

观察者模式和发布-订阅模式的区别

观察者模式是&#xff0c;当被观察者的数据发生变化时&#xff0c;调用被观察者的 notify 方法&#xff0c;去通知所有观察者执行 update 方法进行更新&#xff1b; 对于发布-订阅模式&#xff0c;首先发布者与订阅者互相并不知道彼此的存在&#xff0c;他们是通过事件中心来进…

Element中el-table组件设置max-height右侧出现空白列的解决方法

之前就出现过这个情况&#xff0c;没理过&#xff0c;因为不影响啥除了不美观...但今天看着实在是难受&#xff0c;怎么都不顺眼(可能是我自己烦躁--) 试了很多网上的方法&#xff0c;都不得行&#xff0c;后面发现了这篇文章&#xff0c;解决了! 感谢&#xff01; Element中t…

微知-Mellanox 网卡和NVIDIA Bluefield DPU如何备份firmware?

某些场合需要从网卡或者DPU上读取网卡的firmware 备份命令&#xff1a; flint -d 06:00.0 ri 1.bin实操&#xff1a; 注意&#xff1a; 有些网卡不支持到处firmware

工具软件分享:11个免费的 android数据恢复应用程序功能分析

在手机上丢失数据是一个很大的错误。但是&#xff0c;在这种情况下&#xff0c;除了惊慌失措之外&#xff0c;最好开始使用android数据恢复应用程序搜索以查找将其取回的方法。您可以检查手机的备份存储以在Android上进行数据恢复&#xff0c;但是如果数据仍然无处可寻&#xf…

elementui时间选择器time-picker返回值不对的问题

1. 问题 天杀的elementui的time-picker&#xff0c;导致我开发的系统出现了一次生产问题&#xff0c;原因竟然是因为组件库的bug&#xff01;直接上截图。 如图&#xff0c;正常情况下&#xff0c;选择时间后&#xff0c;想要得到的值理应是当天的时间&#xff0c;如图是当年…

什么是AI网关?AI网关在企业系统中承担什么角色?

AI 大模型的发展正在推动各行业的增长&#xff0c;据有关报告显示&#xff1a;“未来十年内预计年均增长率将达到37.3%&#xff0c;全球企业预计在2027年之前将在AI领域投入8000亿美元"。这一迅猛发展促使许多企业进行战略转型&#xff0c;技术团队也需要调整其构建、运行…

牛客编程初学者入门训练——BC17 缩短二进制

BC17 缩短二进制 描述 我们处理的整数通常用十进制表示&#xff0c;在计算机内存中是以二进制补码形式存储&#xff0c;但通常二进制表示的整数比较长&#xff0c;为了便于在程序设计过程中理解和处理数据&#xff0c;通常采用八进制和十六进制&#xff0c;缩短了二进制补码表…