用c++做贪吃蛇
由于蛇是由多块蛇身组成的,机构体数组或者链表来存储蛇
蛇在运行过程中,如果吃了食物,那么这块食物就可以看作是新的蛇头了,
数组存储
存储新蛇身,在数组的第一个位置插入一个元素。
链表
插入和删除元素效率很高,访问指定元素位置元素
中和上述两种结构的缺点
可以考虑使用队列或者双端队列的方式去存储蛇身
此处我们使用双端队列。
在窗口中绘制出蛇的身子。
函数分析:
·参数:
将蛇作为函数的参数,用矩形框来代替蛇身的每一块,同时用绿色来表示蛇身。以引用方式传递。
避免函数值传递过程中对函数参数进行拷贝,造成不必要的开销。
·返回值:无
游戏结束
游戏结束标志:蛇头碰撞到窗口边界或者蛇头撞到了自己的身体。
函数分析:
· 参数:蛇,一方面要获取到蛇头位置,判断蛇头是否与窗口边界碰撞;另一方面也要获取蛇身,判断蛇头是否碰撞到蛇身。
· 返回值:可以不需要返回值,如果游戏结束,直接在该函数中结束程序即可。
蛇移动
整个蛇放在双端队列中,由于蛇每次超某个方向移动一步,其蛇身位置信息都要改变。不妨将蛇头移动反向的下一个位置的坐标作为新的蛇头,蛇尾部最后一个元素是否需要删除取决于蛇是否迟到了食物:如果没有迟到,则将蛇尾从蛇身中删除;如果吃到了,那么食物的位置就是新的蛇头,由于蛇身长度要加1,则不需要删除蛇尾。然后再重新绘制蛇身。这样一来,蛇就完成了一次移动。
函数分析:
·参数:
·将蛇作为函数的参数,
·用一个标记来标记蛇是否迟到了食物。
·返回值:无
更改蛇的移动方向
从键盘获取输入的按键,完成轮梗概运动的方向
键盘的W、w、上键均可使蛇向上移动;
键盘的S、s、下键均可使蛇向下移动;
键盘的A、a、左键均可使蛇向左移动;
键盘的D、d、右键均可使蛇向右移动;
捕获键盘按键消息
如果捕获到了上述的按键消息,则更改蛇的移动方向,但是注意不可以反方向更改
函数分析:
· 参数:蛇
·返回值:无
生成食物
在屏种随机位置生成一个食物,但注意不应该生成在蛇身上。
函数分析:
·参数:
·食物
·蛇
·返回值:无
在屏幕左上角显示得分
检测是否迟到了食物
及判断蛇头是否与食物重合。
函数分析:
· 参数:蛇,食物。
· 返回值:
bool类型,迟到了返回true,否则返回false
代码如下:
#include<easyx.h>
#include<deque>
using namespace std;
#define Wide 640
#define High 480
#define size 20//边长为20的正方形
#define Delay 200//延迟时间
//蛇移动方向
enum Direction
{
Up,
Down,
Left,
Right
};
//蛇身
struct Snake
{
int x, y;
Direction dir;//移动方向
};
//食物
struct Food
{
int x, y;
};
//绘制蛇身
void drawSnake(deque<Snake>& snake)
{
//绿色表示(设置填充颜色为绿色)
setfillcolor(GREEN);
//遍历蛇身绘制
for (const auto& body : snake)
{
//绘制一个矩形框,四个参数分别是左上角和右下角的横纵坐标
//用20*20的矩形框表示蛇身
fillrectangle(body.x*size,body.y*size,(body.x+1)*size,(body.y+1)*size);
}
//控制蛇移动的速度
Sleep(Delay);
}
//判断游戏是否结束
void isOver(deque<Snake>& snake)
{
//检测碰撞
//遍历蛇身,使用迭代器遍历,从蛇头后面一个元素开始遍历
for (auto iter = snake.begin() + 1; iter != snake.end(); ++iter)
{
if ((snake.front().x == iter->x && snake.front().y == iter->y)//蛇头撞到了自己,游戏结束
||(snake.front().x <0)||(snake.front().x >= Wide/size) //越界,游戏结束
|| (snake.front().y < 0) || (snake.front().y >= High / size)
)
{
//设置当前文字颜色为白色
settextcolor(RED);
//设置当前文字样式,指定高度100,宽度0表示自适应。_T支持Unicode编码C
settextstyle(100,0,_T("楷体"));
TCHAR str[100];
_stprintf_s(str, _T("游戏结束!!!"));
//在指定位置输出字符串。
outtextxy(Wide / size, High / size, str);
//停留三秒
Sleep(3000);
closegraph();//关闭窗口
//直接结束程序
exit(0);
}
}
}
//蛇移动 grow表示是否迟到了食物,该参数用来区分蛇普通移动和吃到食物
void moveSnake(deque<Snake>& snake,bool grow=false)
{
//获取蛇头
Snake newHead = snake.front();
//判断蛇移动方向
switch (newHead.dir)
{
case Up:
newHead.y--;
break;
case Down:
newHead.y++;
break;
case Left:
newHead.x--;
break;
case Right:
newHead.x++;
break;
}
//将新位置作为新蛇头
snake.push_front(newHead);
//每移动一次都要判断游戏是否结束了
isOver(snake);
if (!grow)
{
//没吃到食物
//grow=true表示吃到了食物 grow=false表示普通移动
clearrectangle(snake.back().x * size, snake.back().y * size, (snake.back().x + 1) * size, (snake.back().y + 1) * size);
//将双端队列最后一个元素去除
snake.pop_back();
}
//绘制蛇身
drawSnake(snake);
}
//更改蛇移动方向
void changeDirection(deque<Snake>& snake)
{
ExMessage msg = { 0 };
//捕获按键消息
peekmessage(&msg, EX_KEY);
//当某个键被按下
if (msg.message == WM_KEYDOWN)
{
//判断输入的按键
switch (msg.vkcode)
{
case'w':
case'W':
case VK_UP:
if (snake.front().dir != Down)
snake.front().dir = Up;
break;
case's':
case'S':
case VK_DOWN:
if (snake.front().dir != Up)
snake.front().dir = Down;
break;
case 'a':
case'A':
case VK_LEFT:
if (snake.front().dir != Right)
snake.front().dir = Left;
break;
case 'd':
case'D':
case VK_RIGHT:
if (snake.front().dir != Left)
snake.front().dir = Right;
break;
}
}
}
//生成食物,不能生成在蛇身上
void generateFood(Food& food, deque<Snake>& snake)
{
//一直生成,知道生成的食物为止不在蛇身上
while (true)
{
//随机生成
//将整个窗口看做一个是数组,每个数组元素占的空间大小为20*20个像素点
food.x = rand() % (Wide / size);
food.y = rand() % (High / size);
//用一个变量存储生成的位置是否重合
bool overlap=false;
//遍历蛇身,范围for循环
for (const auto& body : snake)
{
//食物位置与蛇身重合
if (food.x == body.x && food.y == body.y)
{
//已经与蛇身重合了,不必再遍历,跳出for循环,再while循环中重新生成
overlap = true;
break;
}
}
//如果不重合,则食物生成成功,可以结束while循环了
if (!overlap)
{
break;
}
}
}
//检测是否与食物重合
bool checkCollision(deque<Snake>& snake, Food& food)
{
//蛇头与食物重合
if (snake.front().x == food.x && snake.front().y == food.y)
{
return true;
}
//检测是否与蛇身的位置重叠(可以不用,因为蛇头没经过的位置,蛇身必然不会经过)
for (auto iter = snake.begin() + 1; iter != snake.end(); ++iter)
{
if (iter->x == food.x && iter->y== food.y)
{
return true;
}
}
return false;
}
int main()
{
initgraph(Wide, High);//绘制窗口,两个参数分别为窗口的宽度和长度
//定义一条蛇
deque<Snake> snake;
//初始化蛇
//双端队列头部插入一个元素作为蛇头
snake.push_front(Snake{ Wide/size/2,High/size/2,Right });
Food food;
generateFood(food, snake);
//绘制食物
setfillcolor(RED);
fillrectangle(food.x * size, food.y * size, (food.x + 1) * size, (food.y + 1) * +size);
drawSnake(snake);
//分数初始为0
int score = 0;
while (true)
{
//蛇移动
moveSnake(snake);
//更改蛇移动方向
changeDirection(snake);
//检测是否与食物重合
if (checkCollision(snake, food))
{
//蛇吃到食物
score++;
//生成新的食物
generateFood(food, snake);
//true,增加蛇的长度
moveSnake(snake, true);
}
//绘制食物 红色表示食物
setfillcolor(WHITE);
fillrectangle(food.x*size, food.y*size, (food.x +1)* size, (food.y+1)* + size);
//设置当前文字颜色
settextcolor(GREEN);
//设置当前文字样式,指定高度20,宽度0表示自适应。_T支持Unicode编码Consolas表示字体
settextstyle(20,0,_T("楷体"));
TCHAR strScore[16];
_stprintf_s(strScore, _T("得分:%d"), score);
//在指定位置输出字符串。
outtextxy(10, 10, strScore);
}
system("pause");//防止窗口打开即关闭,一闪而过,让其先停一会
closegraph();//关闭窗口
return 0;
}
相关文章:
用c++做贪吃蛇
由于蛇是由多块蛇身组成的,机构体数组或者链表来存储蛇 蛇在运行过程中,如果吃了食物,那么这块食物就可以看作是新的蛇头了, 数组存储 存储新蛇身,在数组的第一个位置插入一个元素。 链表 插入和删除元素效率很高&…...
【UE5.1 角色练习】08-传送技能
前言 在上一篇(【UE5.1 角色练习】07-AOE技能)基础上继续实现人物通过鼠标点击然后传送技能的功能。 效果 步骤 1. 首先需要显示鼠标光标,我们可以在玩家控制器中勾选“显示鼠标光标” 2. 在项目设置中添加一个操作映射,设置按…...
力扣283题:移动零(快慢指针)
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。 请注意 ,必须不复制数组的情况下原地对数组进行操作。 示例 1: 输入: nums [0,1,0,3,12] 输出: [1,3,12,0,0]示例 2: 输入: nums [0] 输出: [0…...
Java面试精粹:高级问题与解答集锦(一)
Java 高级面试问题及答案 问题1:Java中如何实现多线程,以及有哪些线程同步机制? 答案: Java实现多线程主要有两种方式:继承 Thread 类和实现 Runnable 接口。通过继承 Thread 类,可以重写 run() 方法来定…...
Yourpassword does not satisfy the current policyrequirements
mysql 新增数据库用户失败 解决方法: 修改校验密码策略等级 set global validate_password.policyLOW;...
解决vue3 vite打包报Root file specified for compilation问题
解决方法: 修改package.json打包命令 把 "build": "vue-tsc --noEmit && vite build" 修改为 "build": "vite build" 就可以了 另外关于allowJs这个问题,在tsconfig.json文件中配置"allowJs&qu…...
Java Swing + MySQL图书借阅管理系统
系列文章目录 Java Swing MySQL 图书管理系统 Java Swing MySQL 图书借阅管理系统 文章目录 系列文章目录前言一、项目展示二、部分代码1.Book2.BookDao3.DBUtil4.BookAddInternalFrame5.Login 三、配置 前言 项目是使用Java swing开发,界面设计比较简洁、适合作…...
ssm招聘信息管理系统-计算机毕业设计源码78049
摘 要 由于数据库和数据仓库技术的快速发展,招聘客户管理系统建设越来越向模块化、智能化、自我服务和管理科学化的方向发展。招聘客户系统对处理对象和服务对象,自身的系统结构,处理能力,都将适应技术发展的要求发生重大的变化。…...
eBPF可观测之网络流量控制和管理traffic control浅尝
目录 工程背景 环境准备 安装工具 安装依赖包 安装C依赖库 操作步骤 目录结构 代码展示 效果展示 拓展提升 工程背景 首先发表一个"暴论" eBPF在可观测方面的应用,就是各种google。 不需要学习内核,只要掌握ebpf开发套路。…...
Java技术精粹:高级面试问题与解答指南(二)
Java面试问题及答案 1. 什么是Java中的集合框架?请简述其主要接口和类。 答案: Java中的集合框架是一个设计用来存储和操作大量数据的统一架构。它主要由以下几个接口及其实现类组成: Collection: 它是最基本的集合接口,所有单列…...
地下停车场FM信号覆盖系统技术原理用与应用
随着我国城市化水平的快速推进与房地产的快速发展,城市停车场称为每栋建筑物的硬性配套建筑,尤其是商业综合体、医院、政府机关、机场、高铁站等场所出现了超大规模停车场,停放车辆可达数千辆,停车场的智能化与信息化水平也越来越…...
idea 出现 cpu占用100%
一、IDEA的CPU占用率过高 二、解决办法 idea安装路径bin目录 修改idea64.exe.vmoptions配置文件 原来的 -Xms128m -Xmx750m -XX:ReservedCodeCacheSize240m -XX:UseConcMarkSweepGC -XX:SoftRefLRUPolicyMSPerMB50 修改为(IDEA优化内存配置) -Xms2048m -Xmx4096m -XX:Reser…...
如何学到数据库从入门到入土(MySQL篇)
本篇会加入个人的所谓鱼式疯言 ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. 🤭🤭🤭可能说的不是那么严谨.但小编初心是能让更多人能接…...
安卓手机APP开发__Wi-Fi扫描概述
安卓手机APP开发__Wi-Fi扫描概述 目录 概述 Wi-Fi的扫描过程 限制 权限 Android 8.0 and Android 8.1: Android 9: Android 10 (API 级别 29) 和 更高版本: 扫描频率的限制 Android 8.0 and Android 8.1: Android 9: Android 10 and higher: 概述 你能使用Wi-Fi的…...
深入理解二叉树及其在C语言中的实现
一、引言 二叉树是数据结构中一种非常基础且重要的树形结构,它的每个节点最多有两个子节点,通常被称为左子节点和右子节点。二叉树在计算机科学中有着广泛的应用,如搜索、排序、存储数据等。本文将详细介绍二叉树的基本概念、特性以及在C语言…...
基于ssm+vue图书管理系统
基于ssmvue图书管理系统 ssm477图书管理系统 相关技术 javassmmysqlvueelementui...
高防ip能防护变异CC攻击吗
高防ip能防护变异CC攻击吗?随着互联网的不断发展,网络安全问题也日益突出,各类网络攻击层出不穷,其中CC攻击(Challenge Collapsar攻击)及其变种——变异CC攻击,更是让众多企业和个人网站头疼不已…...
从多站点到多活,XEOS 对象数据容灾能力再提升
近日, XSKY SDS V6.4 新版本发布,其中 XEOS V6.4 全新升级并完善了统一命名空间功能,更进一步增强和完善了异地容灾方案,配合强一致代理读,可以实现异地多活;同时大幅降低管理复杂度,有效降低容…...
3D开发工具HOOPS在BIM系统中的应用
建筑信息模型是一种革命性的建筑设计、施工和管理方法。它通过创建和利用数字信息来优化建筑项目的设计、施工和运营过程。在这个过程中,3D开发工具HOOPS扮演着至关重要的角色,为BIM系统提供了强大的技术支持和丰富的功能。HOOPS中文网http://techsoft3d…...
适合下班做的副业兼职、1天挣300,7天涨粉2万
最近小红书上有类视频火了! 周周近财:让网络小白少花冤枉钱,赚取第一桶金 利用AI制作的漫画解说历史小说视频。视频以《明朝那些事儿》为蓝本,一上线就疯狂吸粉,多条视频内容都大爆了。 就是这个账号,仅仅…...
ARL灯塔扫不出指纹?手把手教你用Python脚本批量导入指纹库,提升资产识别准确率
ARL灯塔指纹识别优化实战:Python脚本批量导入与精准率提升指南 资产侦察灯塔(ARL)作为渗透测试领域的重要工具,其核心价值在于准确识别目标资产的技术特征。然而许多中级用户发现,默认指纹库在面对特定行业或新型资产…...
axios 供应链投毒事件完整报告:史上最大 npm 攻击技术分析
axios 供应链投毒事件完整报告:史上最大 npm 攻击技术分析 2026年3月31日 | 安全分析报告 一、事件概述 2026年3月31日,npm 生态遭遇了有记录以来针对顶级包最复杂的供应链攻击。攻击者劫持了 axios(全球每周下载量超 8300 万次)核心维护者的 npm 账号,发布了两个恶意版…...
从Markdown到可执行规范:Tessl Framework初探与“规范即源代码”的实践思考
从Markdown到可执行规范:Tessl Framework初探与“规范即源代码”的实践思考 当代码行数不再是衡量开发效率的唯一标准,一种全新的编程范式正在悄然兴起。想象一下,开发者不再需要直接编写实现细节,而是专注于用结构化的自然语言描…...
QT 5.14.0实战:手把手教你用QLineEdit打造一个带验证码的登录框(附完整样式代码)
QT 5.14.0实战:手把手教你用QLineEdit打造一个带验证码的登录框(附完整样式代码) 在GUI开发中,登录界面是最基础也最考验细节的组件之一。一个优秀的登录框不仅需要功能完整,还要在用户体验上下足功夫——比如实时输入…...
OpenJSCAD.org与3D打印完美结合:从代码到实物的完整工作流程
OpenJSCAD.org与3D打印完美结合:从代码到实物的完整工作流程 【免费下载链接】OpenJSCAD.org JSCAD is an open source set of modular, browser and command line tools for creating parametric 2D and 3D designs with JavaScript code. It provides a quick, pr…...
OpenSees数值模拟从入门到进阶:理论、代码与实践
OpenSees数值模拟从入门到进阶:理论、代码与实践 摘要 OpenSees(Open System for Earthquake Engineering Simulation)作为开源的地震工程模拟系统,凭借其强大的非线性分析能力和开放的架构,已成为结构地震响应分析领域的重要工具。本文系统介绍OpenSees数值模拟的基本原…...
告别满屏窗口!AI智能体杀入职场,企业软件迎来“大洗牌”
SaaS不会像本地部署软件那样走向消亡,但随着AI更深入地渗透到推动企业运营的系统中,IT领导者在管理各类AI时面临着巨大挑战。今年1月,Anthropic低调发布软件插件,引发了SaaS类股票的疯狂抛售。在接下来的两周里,金融市…...
动态间隙精准诊断:NHJX-13 型底盘间隙仪机动车底盘安全检测全方案
动态间隙精准诊断:NHJX-13 型底盘间隙仪机动车底盘安全检测全方案在机动车安全环保检测体系中,底盘间隙仪是诊断车辆转向机构、悬挂系统、传动部件间隙状况的核心设备,尤其对大中型客车、重中型货车等营运车辆,其性能直接决定底盘…...
AI 大模型落地系列|Eino ADK体系篇:你对 ChatModelAgent 有了解吗?
声明:本文源于官方文档,重点参考 Eino ADK: ChatModelAgent、Eino ADK: 概述、Eino ADK: Agent 协作 为什么很多人把 ChatModelAgent 想简单了?一文讲透 ReAct、Transfer、AgentAsTool 与 Middleware1. 为什么很多人会把 ChatModelAgent 想简…...
3分钟搞定加密音乐:Unlock-Music浏览器解密终极指南
3分钟搞定加密音乐:Unlock-Music浏览器解密终极指南 【免费下载链接】unlock-music 在浏览器中解锁加密的音乐文件。原仓库: 1. https://github.com/unlock-music/unlock-music ;2. https://git.unlock-music.dev/um/web 项目地址: https:/…...
