【C/C++ 11】贪吃蛇游戏

news2024/11/24 9:40:59

一、题目

贪吃蛇游戏机制是通过控制蛇上下左右移动并吃到食物得分。

蛇头碰到墙壁或者碰到蛇身就游戏结束。

食物随机生成,蛇吃到食物之后蛇身变长,蛇速加快。

二、算法

1. 初始化游戏地图并打印,地图的边缘是墙,地图的每个坐标都有属性(EMPTY、WALL、FOOD、HEAD、BODY),通过<Window.h>库里面的函数控制光标跳转和颜色。

2. 初始化蛇,蛇是一个单独的类,类里面的属性有蛇头、蛇身、长度、速度,蛇头一个SnakeNode节点,蛇身是一个SnakeNode指针,每个SnakeNode都是一个x、y坐标,用于表示蛇在地图上的位置。

3. 随机生成食物,蛇移动的下一步如果是食物则得分,若下一步是墙壁或蛇身则游戏失败。

4. 通过键盘输入控制方向,若键盘没有输入则保持方向不变。

三、代码

#define _CRT_SECURE_NO_WARNINGS 1

#pragma warning (disable:4996)
#include <iostream>
#include <Windows.h>
#include <conio.h>
#include <ctime>
#include <vector>
using namespace std;

#define ROW 22
#define COL 42

#define EMPTY 0
#define WALL  1
#define FOOD  2
#define HEAD  3
#define BODY  4

#define COL_WALL  6
#define COL_FOOD  12
#define COL_SNAKE 10

#define UP 72
#define DOWN 80
#define LEFT 75
#define RIGHT 77
#define SPACE 32
#define ESC 27
#define ENTER 13

int g_map[ROW][COL] = { 0 };
int g_grade = 0;

void CursorJump(int x, int y)
{
	COORD pos;    //定义光标位置的结构体变量
	pos.X = x;
	pos.Y = y;
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);        //设置光标位置
}

void Color(int x)
{
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), x);    //设置颜色
	// 6——土黄色    7——白色    10——绿色    12——红色
}

void SysInit()
{
	srand((unsigned int)time(NULL));
	system("title 贪吃蛇");
	system("mode con cols=84 lines=23");    //设置终端窗口大小
	CONSOLE_CURSOR_INFO curInfo;    //光标信息结构体变量
	curInfo.dwSize = 1;
	curInfo.bVisible = FALSE;        //光标光标隐藏不可见
	SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &curInfo);    //设置光标信息
}

void MapInit()
{
	for (int i = 0; i < ROW; ++i)
	{
		for (int j = 0; j < COL; ++j)
		{
			CursorJump(2 * j, i);
			if (i == 0 || i == ROW - 1 || j == 0 || j == COL - 1)
			{
				Color(COL_WALL);
				g_map[i][j] = WALL;
				cout << "■";
			}
			else
			{
				g_map[i][j] = EMPTY;
				cout << "  ";
			}
		}
	}
	Color(7);
	CursorJump(0, ROW);
	cout << "当前得分是:" << g_grade;
}

void RandFood()
{
	int row, col;
	do
	{
		row = rand() % ROW;
		col = rand() % COL;
	} while (g_map[row][col] != EMPTY);
	g_map[row][col] = FOOD;
	Color(COL_FOOD);
	CursorJump(2 * col, row);
	cout << "●";
}

class Snack
{
public:
	Snack()
	{
		len = 2;
		rate = 3000;

		head.x = COL / 2;
		head.y = ROW / 2;
		g_map[head.y][head.x] = HEAD;

		body.resize(ROW * COL, Pos(0, 0));
		for (int i = 0; i < len; ++i)
		{
			body[i].x = head.x - i - 1;
			body[i].y = head.y;
			g_map[body[i].y][body[i].x] == BODY;
		}
	}

	void PrintSnake(int flag)
	{
		if (flag)
		{
			// 打印蛇
			Color(COL_SNAKE);
			CursorJump(2 * head.x, head.y);
			cout << "◆";
			for (int i = 0; i < len; ++i)
			{
				CursorJump(2 * body[i].x, body[i].y);
				cout << "◇";
			}
		}
		else
		{
			// 覆盖蛇
			if (body[len - 1].x != 0)
			{
				CursorJump(2 * body[len - 1].x, body[len - 1].y);
				cout << "  ";
			}
		}
	}

	void Judge(int x, int y)
	{
		if (g_map[head.y + y][head.x + x] == FOOD)
		{
			// 得分
			g_grade += 10;

			len++;
			if (rate > 1000)
				rate -= 50;
			Color(7);
			CursorJump(0, ROW);
			cout << "当前得分是:" << g_grade;
			RandFood();
		}
		else if (g_map[head.y + y][head.x + x] == WALL
			|| g_map[head.y + y][head.x + x] == BODY)
		{
			// 失败
			Sleep(2000);
			Color(7);
			system("cls");
			cout << "           GAME OVER!          " << endl;
			cout << "            游戏失败!          " << endl;
			exit(0);
		}
	}

	void Move(int x, int y)
	{
		Judge(x, y);
		PrintSnake(0);
		int tail = len - 1;
		g_map[body[tail].y][body[tail].x] = EMPTY;
		while (tail > 0)
		{
			body[tail].x = body[tail - 1].x;
			body[tail].y = body[tail - 1].y;
			--tail;
		}
		body[0].x = head.x;
		body[0].y = head.y;
		g_map[body[0].y][body[0].x] = BODY;
		head.x += x;
		head.y += y;
		g_map[head.y][head.x] = HEAD;
		PrintSnake(1);
	}

	void Run(int x, int y)
	{
		int t = 0;
		while (1)
		{
			if (t == 0)
				t = rate;

			while (--t)
			{
				if (kbhit() != 0)
					break;
			}

			if (t == 0)
				Move(x, y);
			else
				break;
		}
	}

	void Play()
	{
		int dir = RIGHT;
		int old = dir;
		while (1)
		{
			switch (dir)
			{
			case 'w':
			case 'W':
			case UP:
				Run(0, -1);
				old = dir;
				break;
			case 's':
			case 'S':
			case DOWN:
				Run(0, 1);
				old = dir;
				break;
			case 'a':
			case 'A':
			case LEFT:
				Run(-1, 0);
				old = dir;
				break;
			case 'd':
			case 'D':
			case RIGHT:
				Run(1, 0);
				old = dir;
				break;
			case SPACE:
				system("pause>nul");
				break;
			case ESC:
				system("cls");
				cout << "   ESC 退出游戏" << endl;
				exit(0);
			}

			dir = getch();
			switch (dir)
			{
			case 'w':
			case 'W':
			case UP:
			case 's':
			case 'S':
			case DOWN:
				if (old == UP || old == DOWN)
					dir = old;
				break;
			case 'a':
			case 'A':
			case LEFT:
			case 'd':
			case 'D':
			case RIGHT:
				if (old == LEFT || old == RIGHT)
					dir = old;
				break;
			case SPACE:
			case ESC:
				break;
			default:
				dir = old;
			}
		}
	}

private:
	struct Pos
	{
		int x, y;

		Pos() {}
		Pos(int x1, int y1)
			: x(x1), y(y1)
		{}
	};

	Pos head;
	vector<Pos> body;
	int len;
	int rate;
};

int main()
{
	SysInit();
	MapInit();
	RandFood();

	Snack s;
	s.Play();

	return 0;
}

四、测试

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

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

相关文章

移动Web——less

1、less-简介 less是一个CSS预处理器&#xff0c;Less文件后缀是.less。扩充了CSS语言&#xff0c;使CSS具备一定的逻辑性、计算能力注意&#xff1a;浏览器不识别Less代码&#xff0c;目前阶段&#xff0c;网页要引入对应的CSS文件VS code插件&#xff1a;Easy LESS&#xff…

初始数据库

华子目录 什么是数据库DBMS&#xff08;数据库管理系统&#xff09;数据库系统和文件系统的区别文件系统数据库系统对比区别优缺点总结 常见数据库关系型数据库ACID原则关系型数据库的优缺点优点缺点 非关系型数据库存储方式常见的非关系型数据库非关系型数据库的优缺点优点缺点…

OpenSSL:configure: error: OpenSSL library not found解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

MATLAB计算多边形质心/矩心

前言&#xff1a;不规则四边形的中心 不规则四边形的出心有多种定义&#xff0c;以下是最常见的三种&#xff1a; 1.重心&#xff1a;重心是四边形内部所有顶点连线交点的平均位置。可以通过求解四个顶点坐标的平均值来找到重心。 2.质心&#xff1a;质心是四边形内部所有质点…

网络原理-TCP/IP(5)

TCP协议 延迟应答 它也是基于滑动窗口,提高效率的一种机制,结合滑动窗口以及流量控制,能够以延迟应答ACK的方式,把反馈的窗口,搞大.核心在于允许范围内,让窗口尽可能大. 如果接收数据的主机立刻返回ACK应答,这时候返回的窗口可能比较小. 1.假设接收端缓冲区为1M.一次收到了5…

一站式SpringBoot学习平台:让编程变得轻松有趣!

介绍&#xff1a;Spring Boot是一个开源的Java框架&#xff0c;旨在简化Spring应用程序的开发和部署过程。 Spring Boot由Pivotal团队设计并推出&#xff0c;它的核心优势在于极大地简化了传统Spring应用的初始搭建和开发流程。具体来说&#xff0c;Spring Boot的主要特点包括&…

git 合并多条提交记录

我要合并多条提交记录&#xff08;合并前7条为一条&#xff09;&#xff0c;实现如下效果&#xff1a; 使用git rebase // 查看前10个commit git log -10 // 将7个commit压缩成一个commit&#xff1b;注意&#xff1a;vim编辑器 git rebase -i HEAD~4 // add已经跟踪的文件 g…

C++11多线程:线程的创建及启动

文章目录 启动线程传递函数对象为参数传递成员函数为参数传递全局函数为参数传递lambda函数为参数也可调用std::thread的无参构造 join()、joinable()、detach() 等函数Join函数detach 函数joinable函数 Join函数到底干了什么&#xff1f;必须join或者detach吗&#xff1f;线程…

AI少女/HS2甜心选择2 仿碧蓝航线人物卡全合集打包

AI少女/HS2甜心选择2 仿碧蓝航线人物卡全合集打包 内含&#xff1a;埃吉尔 女仆装花园 新泽西 白雪之仪库尔斯克信浓泳装埃吉尔风纪委员大凤路易九世旗袍能代夜响的绝园英仙座 护士 下载地址&#xff1a; https://www.changyouzuhao.cn/13366.html

springboot153相亲网站

简介 【毕设源码推荐 javaweb 项目】基于springbootvue 的 适用于计算机类毕业设计&#xff0c;课程设计参考与学习用途。仅供学习参考&#xff0c; 不得用于商业或者非法用途&#xff0c;否则&#xff0c;一切后果请用户自负。 看运行截图看 第五章 第四章 获取资料方式 **项…

ONLYOFFICE 8.0 测评:重塑办公新标杆,你绝对不能错过的版本!

ONLYOFFICE 8.0 测评&#xff1a;办公新境界的全新突破 一、全新的界面设计二、可填写的 PDF 表单 免费表单模板三、双向文本四、电子表格中的新增功能五、协作功能升级六、跨平台性能优化七、强化安全性八、更丰富的插件生态九、辅助功能&#xff1a;优化的屏幕朗读器 随着科…

程序员阿宝过年-UMLChina建模知识竞赛第5赛季第5轮

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 参考潘加宇在《软件方法》和UMLChina公众号文章中发表的内容作答。在本文下留言回答。 只要最先答对前3题&#xff0c;即可获得本轮优胜。 如果有第4题&#xff0c;第4题为附加题&am…

Ubuntu+GPU搭建Stable-Diffusion教程

【前序】已经安装anaconda 1.git拉取项目到本地 执行git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui.git 进入项目目录下 cd stable-diffusion-webui/ 2. 安装对应Python依赖包 首先安装pytorch和torchvision&#xff0c;若是GPU环境的用户需要安装与cu…

[基础IO]动静态库{创建/使用/加载}

文章目录 1.创建静态库2.使用静态库3.动态库 1.创建静态库 预备知识: gcc main.c mymath.c myprint.c -o my.exe / gcc main.o mymath.o myprint.o -o my.exe三个.c/.o文件可以编译成为可执行程序 编写源文件与头文件[库的源文件没有main函数]将所有的源文件编译生成.o文件。(…

电工需要掌握的电路

1、通用型变频器接线示意图 2、三线式运转控制台达正反转电路图 3、单相220V接线实物图、三相380V接线实物图 4、变频器操作面板功能介绍 5、风暖浴霸实物接线电路图 6、车辆出入门闸检测实物接线电路图 7、电位器实现两台变频器同步调频实物接线图 8、门禁系统是如何工作的实物…

解决zabbix图像中文乱码

使用zabbix查看监控图像信息&#xff0c;发现会有中文乱码现象。 解决方法如下&#xff1a; 1.拷贝windows文字文件到服务器上 C:\Windows\Fonts目录下拷贝自己需要的中文语言文件 2.修改配置文件 vim /usr/share/zabbix/include/defines.inc.php 81行 define(ZBX_GRAPH_F…

vue3接入微信扫码授权登录流程

一、概要 本篇主要介绍两点,相关文档请查阅微信开平台 准备工作 | 微信开放文档 微信开放平台的登录授权相关流程vue3如何接入微信开放平台的微信授权登录功能二、微信开放平台的登录授权相关流程 第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应…

6个.NET开源且强大的快速开发框架(帮助你提高生产效率)

中台Admin&#xff08;Admin.Core&#xff09; 中台Admin&#xff08;Admin.Core&#xff09;是前后端分离权限管理系统&#xff0c;前端 UI 基于Vue3开发&#xff0c;后端 Api 基于.NET 8.0开发。支持多租户、接口权限、数据权限、动态 Api、任务调度、OSS 文件上传、滑块拼图…

格式化日期注解@JsonFormat的使用和TimeZone时区问题

JsonFormat的使用 目的 为了便于date类型字段的序列化和反序列化&#xff0c;需要在数据结构的Date、Timestamp、DateTime类型的字段上用JsonFormat注解进行注解 使用 JsonFormat注解是一个时间格式化注解&#xff0c;比如我们存储在mysql中的数据是date类型的&#xff0c;当…

qml为程序设置图标(100%成功!3步搞定!)

步骤1 打开 CMakeLists.txt 文件&#xff0c;在 main.cpp 这行代码下面&#xff0c;添加一句&#xff1a;icon.rc。 步骤2 此时 icon.rc 这个文件还不存在&#xff0c;我们需要在目录中新建一个 .txt 文件&#xff0c;然后把文件名和后缀名改为 icon.rc。 步骤3 在 Qt Creat…