用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制作的漫画解说历史小说视频。视频以《明朝那些事儿》为蓝本,一上线就疯狂吸粉,多条视频内容都大爆了。 就是这个账号,仅仅…...
CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...
linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...
2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
零基础设计模式——行为型模式 - 责任链模式
第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...
SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...
(一)单例模式
一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...
Ubuntu Cursor升级成v1.0
0. 当前版本低 使用当前 Cursor v0.50时 GitHub Copilot Chat 打不开,快捷键也不好用,当看到 Cursor 升级后,还是蛮高兴的 1. 下载 Cursor 下载地址:https://www.cursor.com/cn/downloads 点击下载 Linux (x64) ,…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
认识CMake并使用CMake构建自己的第一个项目
1.CMake的作用和优势 跨平台支持:CMake支持多种操作系统和编译器,使用同一份构建配置可以在不同的环境中使用 简化配置:通过CMakeLists.txt文件,用户可以定义项目结构、依赖项、编译选项等,无需手动编写复杂的构建脚本…...
算法打卡第18天
从中序与后序遍历序列构造二叉树 (力扣106题) 给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。 示例 1: 输入:inorder [9,3,15,20,7…...
