Qt6_贪吃蛇Greedy Snake
贪吃蛇Greedy Snake
1分析
首先这是一个贪吃蛇界面,由一个长方形边框和一只贪吃蛇组成

默认开局时,贪吃蛇身体只有3个小方块,使用画笔画出
1.1如何移动
对于蛇的移动,有2种方法
- 在一定时间范围内(定时器),未对游戏做出操作(前后左右移动),则整个身体向面朝方向移动一格
- 在一定时间范围内(定时器),未对游戏做出操作(前后左右移动),则身体最前面加上一格方块,身体最后面减去一个方块
这里使用第2种方法
如图,有4个坐标,AC分别是原蛇的头部方格的两个坐标
则新产生的方格的B点为(x1,y1-方格高度);D点(x3,y3-方格高度)

注意
向某个方向增加不能无限增加下去,当触碰到顶部时,我们可以设置条件:
- 死亡
- 穿过从另一个方向开始
这里我们采用第2种方式
1.2向上
如图,此时BD点已经超过x轴,即高度为0的位置

因此我们可以判断:当蛇头部的方格A/C的高度 - 1个方格的高度 < 0 时,则从底部开始进入

-
移动前:x3=x1+蛇宽度;y3=y1
-
移动后:x2=x1,y2=窗口高度-蛇宽度;x4=x2+蛇宽度,y4=y2
1.3向下
同理,向下走只要最下面增加,最上面减少即可

-
移动前:x4=x2+蛇宽度;y2=y4
-
移动后:x1=x2,y1=0;x3=x1+蛇宽度,y3=蛇高度
1.4向左
-
移动前:x3=x2+蛇宽;y3=y2+蛇高
-
移动后:x1=x2-蛇宽,y1=y2;x4=x2,y4=y3

穿越
- x2=窗口宽度-蛇宽,y2=y1
- x3=窗口宽度,y3=y4

1.5向右
-
移动前:x4=x1+蛇宽;y4=y1+蛇高
-
移动后:x2=x1+蛇宽,y2=y1;x3=x4+蛇宽,y3=y4

穿越
- x2=0,y2=y1;
- x3=蛇宽,y3=y4

2如何成长
在界面的不同地方会默认刷新出一个球,蛇吃了这个球身体就会增加一格,同时球消失刷新出现在其他地方

判断球是否被吃掉:即判断蛇的身体是否与球重合,如果重合,增加身体1,同时刷新球出现的位置
3代码
widget.h
#ifndef WIDGET_H
#define WIDGET_H#define OUTTIME 100 //超时时间
#define SNAKE_WIDTH 20 //蛇的一个方格宽度
#define SNAKE_HEIGHT 20 //蛇的一个方格高度
#include <QWidget>
#include<QKeyEvent>
#include<QDebug>
#include<QTimer>
#include<QPixmap>
#include<QPainter>
#include<random>
#include<QTime>
#include <QRandomGenerator>/*0.创建蛇要求:可以实现前面删除后面增加,可以用LIST链表1.按键处理2.使用定时器2.1关联信号槽2.2启动定时器2.3实现对应的超时处理(timeOut)函数3.渲染图像
*/QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
//定义方向
enum Direction
{LEFT,RIGHT,UP,DOWN
};
class Widget : public QWidget
{Q_OBJECT
public:Widget(QWidget *parent = nullptr);~Widget();
protected://按键处理void keyPressEvent(QKeyEvent *event);//添加头部void addTOP();void addBUTOM();void addLEFT();void addRIGHT();//绘制界面void paintEvent(QPaintEvent *event);//删除尾部void deleLAST();//初始化食物void initFood();//判断是否碰撞bool isIntersect();
private:Ui::Widget *ui;int moveFlag = UP; //方向标志bool gameStatu = false;//游戏状态//bool isIntersect = false;//定时器QTimer *timer;//事物QRectF food;//创建蛇QList<QRectF> snake;
protected slots:void timeOut();//超时函数
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);this->resize(450,300);//使用定时器timer = new QTimer();//发出信号//连接信号connect(timer,SIGNAL(timeout()),this,SLOT(timeOut()));//初始化蛇QRectF rect(this->width()/2,this->height()/2,SNAKE_WIDTH,SNAKE_HEIGHT);snake.append(rect); //蛇身+1addTOP(); //蛇身+1addTOP();//初始化食物initFood();
}Widget::~Widget()
{delete ui;
}//按键绑定:控制方向
void Widget::keyPressEvent(QKeyEvent *event)
{switch(event->key()){case Qt::Key_Up:if(moveFlag != DOWN){moveFlag = UP;}break;case Qt::Key_Down:if(moveFlag != UP){moveFlag = DOWN;}break;case Qt::Key_Left:if(moveFlag != RIGHT){moveFlag = LEFT;}break;case Qt::Key_Right:if(moveFlag != LEFT){moveFlag = RIGHT;}break;case Qt::Key_Space:if(!gameStatu){gameStatu = true;//启动定时器timer->start(OUTTIME);}else{gameStatu = false;timer->stop();}break;default:return;break;}
}//顶部增加
void Widget::addTOP()
{QPointF leftTop; //左上点QPointF rightBotom; //右下点if(snake[0].y() - SNAKE_HEIGHT < 0 ) //如果超过顶部{leftTop = QPoint(snake[0].x(),this->height() - SNAKE_HEIGHT);rightBotom = QPoint(snake[0].x() + SNAKE_WIDTH,this->height());}else //未超过顶部{leftTop = QPointF(snake[0].x(),snake[0].y() - SNAKE_HEIGHT);rightBotom = snake[0].topRight();}snake.insert(0,QRectF(leftTop,rightBotom));
}void Widget::addBUTOM()
{QPointF leftTop;QPointF rightBotom;if(snake[0].y() + 2*SNAKE_HEIGHT > this->height() ) //如果超过底部{leftTop = QPointF(snake[0].topLeft().x(),0);// 原x 0rightBotom = QPointF(snake[0].bottomRight().x(),SNAKE_HEIGHT);// 右下x+蛇宽 蛇高}else //未超过底部{leftTop = snake[0].bottomLeft();rightBotom = snake[0].bottomRight()+QPointF(0,SNAKE_HEIGHT);}snake.insert(0,QRectF(leftTop,rightBotom));
}void Widget::addLEFT()
{QPointF leftTop;QPointF rightBotom;if(snake[0].x()-SNAKE_WIDTH < 0 ) //超过边缘{leftTop = QPointF(this->width()-SNAKE_WIDTH,snake[0].topLeft().y());// 窗口宽-蛇宽 左上原y不变rightBotom = QPointF(this->width(),snake[0].bottomRight().y());// 窗口宽 右下原y不变}else //未超过{leftTop = QPointF(snake[0].topLeft().x()-SNAKE_WIDTH,snake[0].topLeft().y());// 左上x-蛇宽 左上原y不变rightBotom = QPointF(snake[0].bottomRight().x()-SNAKE_WIDTH,snake[0].bottomRight().y());// 右下x-蛇宽 右下原y不变}snake.insert(0,QRectF(leftTop,rightBotom));
}void Widget::addRIGHT()
{QPointF leftTop;QPointF rightBotom;if(snake[0].x()+SNAKE_WIDTH*2 > this->width() ) //超过边缘{leftTop = QPointF(0,snake[0].topLeft().y());// 0 左上原y不变rightBotom = QPointF(SNAKE_WIDTH,snake[0].bottomRight().y());// 蛇宽 右下原y不变}else //未超过边缘{leftTop = QPointF(snake[0].topLeft().x()+SNAKE_WIDTH,snake[0].topLeft().y());// 左上x-蛇宽 左上原y不变rightBotom = QPointF(snake[0].bottomRight().x()+SNAKE_WIDTH,snake[0].bottomRight().y());// 右下x-蛇宽 右下原y不变}snake.insert(0,QRectF(leftTop,rightBotom));
}//绘制界面
void Widget::paintEvent(QPaintEvent *event)
{QPainter painter(this);QPen pen;//画笔QBrush brush;//画刷//加载背景图片QPixmap pix;pix.load(":/background/bg_1.jpg");painter.drawPixmap(0,0,pix.width(),pix.height(),pix);//绘制蛇pen.setColor(Qt::black); //设定画笔颜色brush.setColor(Qt::darkMagenta);//画刷颜色brush.setStyle(Qt::SolidPattern);//画刷风格painter.setPen(pen); //画家配置画笔painter.setBrush(brush);//画家配置画刷for(int i=0;i<snake.length();i++){painter.drawRect(snake[i]);//画家进行绘画}//绘制食物brush.setColor(Qt::yellow);//画刷颜色brush.setStyle(Qt::SolidPattern);//画刷风格painter.setPen(pen); //画家配置画笔painter.setBrush(brush);//画家配置画刷painter.drawEllipse(food);//绘制结束面板if(isIntersect()){QFont font("微软雅黑",30,QFont::ExtraLight,false);painter.setFont(font);painter.drawText(this->width()/2-120,this->height()/2,QString("GAME OVER!"));timer->stop();}
}//去尾
void Widget::deleLAST()
{snake.removeLast();
}// 初始化食物
void Widget::initFood()
{ //QRandomGenerator::global()->generate()随机生成数字food = QRectF(QRandomGenerator::global()->generate()%(this->width()/20)*20,QRandomGenerator::global()->generate()%(this->height()/20)*20,SNAKE_WIDTH,SNAKE_HEIGHT);
}//是否碰撞
bool Widget::isIntersect()
{for(int i=1;i<snake.length();i++){if(snake[0] == snake[i]){return true;}}return false;
}//超时函数
void Widget::timeOut()
{int count =1;if(snake[0].intersects(food)){count++;//重新初始化食物,即令其刷新位置initFood();}while(count--){switch (moveFlag){case UP:addTOP();break;case DOWN:addBUTOM();break;case LEFT:addLEFT();break;case RIGHT:addRIGHT();break;default:return;break;}}deleLAST();update(); //重新绘制,即更新图像
}
4效果
//重新初始化食物,即令其刷新位置
initFood();
}
while(count–)
{
switch (moveFlag)
{
case UP:
addTOP();
break;
case DOWN:
addBUTOM();
break;
case LEFT:
addLEFT();
break;
case RIGHT:
addRIGHT();
break;
default:
return;
break;
}
}
deleLAST();
update(); //重新绘制,即更新图像
}
## 4效果
相关文章:
Qt6_贪吃蛇Greedy Snake
贪吃蛇Greedy Snake 1分析 首先这是一个贪吃蛇界面,由一个长方形边框和一只贪吃蛇组成 默认开局时,贪吃蛇身体只有3个小方块,使用画笔画出 1.1如何移动 对于蛇的移动,有2种方法 在一定时间范围内(定时器),未对游戏…...
Credo推出业界首款单片集成CMOS VCSEL驱动器的800G光DSP芯片
针对AOC及短距(SR)光模块优化的新型Credo DSP,适用于下一代超大规模数据中心/AI应用 加州圣何塞和中国深圳,2023年9月6日——Credo Technology(纳斯达克股票代码:CRDO)今日发布两款新品&#x…...
【经验分享】如何使用VSCode对比两个文件
问题: 当有两个不同版本的文件,如何使用VSCode对比两个文件 解决办法 长按ctrl选择想要对比的两个文件-----右键选择将已选项进行比较----大功告成 大功告成...
从裸机开始安装ubuntu系统到安装NVIDIA驱动
这篇文章为总结类文章,更多的是把各个博主的内容总结一下,形成一套端到端的方法,主要内容包括: 安装ubuntu22.04版本(含启动U盘制作)配置ssh、固定ip和端口号安装NVIDIA驱动安装cuda11.7和cudnn8.6 文章目录 一、安装ubuntu22.041…...
索尼 toio™ 应用创意开发征文|小巧机器,大无限,探索奇妙世界
文章目录 前言微型机器人的未来:toio™小机器人简介toio™小机器人:创新功能一览toio™小机器人:多领域的变革者toio™小机器人贪吃蛇游戏代码实现写在最后 前言 当我们谈到现代科技的创新时,往往会联想到复杂的机器和高级的编程…...
什么牌子的led台灯质量好?热门的Led护眼台灯推荐
led台灯有环保无污染、耗能低、长寿命等优点,适合用在阅读、书写、批阅等办公或学习的场所。而挑选LED台灯时,分散光挡板做的比较好的优先选择,能分散大量蓝光,对眼睛危害较小。下面,小编为大家推荐五款质量好的led护眼…...
预推免,保研------长安大学保内,附加分面试准备【记录帖】
🚀长安大学——人工智能系——程惠泽 🚌前六学期专业排名:7/82 🚌信息门户GPA:3.94 🚌平均成绩:89.83 🚌加权成绩:89.15 / ☁️本人比较菜,只能保研本校&…...
Linux开源防病毒引擎ClamAV
ClamAV官方地址:https://www.clamav.net 它支持Linux、BSD、windows、Mac OS X等系统。 在CentOS 8(Tencent OS 3.1)安装非常便利,可以使用yum。 yum install clamav 安装成功,就可以使用它进行病毒扫描检查了。 c…...
Java复习-25-单例设计模式
单例设计模式 目的(使用场景) 在实际开发下,会存在一种情况:某一种类在程序的整个生命周期中,只需要实例化一次就足够了。例如,系统数据类,由于操作系统只有一个,因此在程序初始化…...
博客系统自动化测试项目实战(测试系列9)
目录 前言: 1.博客前端页面测试用例图 2.测试用例的代码实现 2.1登录页面的测试 2.2博客列表页面的测试 2.3写博客测试 2.4博客详情页面的测试 2.5已发布博客的标题和时间的测试 2.6注销用户的测试 结束语: 前言: 之前小编给大家讲…...
华纳云:Linux的底层体系结构是怎样的
Linux操作系统的底层体系结构是一个开源的Unix-like操作系统内核,通常称为Linux内核(Linux Kernel)。下面是Linux底层体系结构的主要组成部分和工作原理: 内核(Kernel): Linux的核心部分是内核,它是操作系统…...
SpringMVC常用注解介绍及参数传递说明
前言 上一篇文章介绍了SpringMVC是什么以及它的工作流程和核心组件,介绍入门示例时,提到了RequestMapping注解,那么这篇文章就来介绍SpringMVC中更多的常用的注解,以及它的参数传递。 一. SpringMVC常用注解 1.1 RequestParam …...
4 个你可能不知道的 Python 迭代工具过滤器函数
推荐:使用 NSDT场景编辑器 快速搭建3D应用场景 当您只想循环遍历迭代器、检索序列中的元素并处理它们时,这些元素特别有用 - 所有这些都无需将它们存储在内存中。今天我们将学习如何使用以下四个迭代工具过滤器函数: filterfalsetakewhiledr…...
Scrapy简介-快速开始-项目实战-注意事项-踩坑之路
scrapy项目模板地址:https://github.com/w-x-x-w/Spider-Project Scrapy简介 Scrapy是什么? Scrapy是一个健壮的爬虫框架,可以从网站中提取需要的数据。是一个快速、简单、并且可扩展的方法。Scrapy使用了异步网络框架来处理网络通讯&…...
lightdb 支持兼容Oracle的to_clob函数
文章目录 概述案例演示 概述 在信创移植的SQL语句中,有来源于Oracle数据库的SQL语句。 在ORACLE PL/SQL包中,你可以使用TO_CLOB(character)函数将RAW、CHAR、VARCHAR、VARCHAR2、NCHAR、NVARCHAR2、CLOB值转换为CLOB。 因此在LightDB 23.3版本中实现了…...
ES6中let和const关键字与var关键字之间的区别?
聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 变量作用域(Scope):⭐ 变量提升(Hoisting):⭐ 重复声明:⭐ 初始化:⭐ 全局对象属性:⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#…...
Python中的异常处理3-1
Python中的异常指的是语法上没有错误,但是代码执行时会导致错误的情况。 1 抛出异常 在图1所示的代码中,要求用户输入一个数字,该代码在语法上没有错误。 图1 出现异常的代码 但是运行该代码之后,如果用户输入的是数字…...
大数据与AI:解析智慧城市的幕后英雄
文章目录 1. 智慧城市的定义与发展2. 大数据:智慧城市的基石2.1 大数据的概念与重要性2.2 大数据的应用案例2.2.1 智能交通管理2.2.2 能源效率优化2.2.3 城市规划与土地利用 3. 人工智能:智慧城市的大脑3.1 人工智能的概念与重要性3.2 人工智能的应用案例…...
将钉钉机器人小程序从一个公司迁移至另一个公司的步骤
引言: 由于我们以前开发的钉钉小程序都在一个公司,想在想应用到另一个公司,这就牵扯出了关于钉钉小程序迁移方面的具体步骤。下面是具体步骤: 1、创建一个钉钉小程序 在这一步你需要有钉钉开放平台的开发者权限,具体…...
j解决Ubuntu无法安装pycairo和PyGObject
环境:虚拟机Ubuntu20.04,vscode无法安装pycairo和PyGObject 虚拟机Ubuntu20.04,vscode中运行Anaconda搭建的vens 的Python3.8.10 首先在vscode中点击ctrlshiftp,选择Python3.8.10的环境,自动激活Python 最近在搞无人…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...
IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...
密码学基础——SM4算法
博客主页:christine-rr-CSDN博客 专栏主页:密码学 📌 【今日更新】📌 对称密码算法——SM4 目录 一、国密SM系列算法概述 二、SM4算法 2.1算法背景 2.2算法特点 2.3 基本部件 2.3.1 S盒 2.3.2 非线性变换 编辑…...
PLC入门【4】基本指令2(SET RST)
04 基本指令2 PLC编程第四课基本指令(2) 1、运用上接课所学的基本指令完成个简单的实例编程。 2、学习SET--置位指令 3、RST--复位指令 打开软件(FX-TRN-BEG-C),从 文件 - 主画面,“B: 让我们学习基本的”- “B-3.控制优先程序”。 点击“梯形图编辑”…...
java 局域网 rtsp 取流 WebSocket 推送到前端显示 低延迟
众所周知 摄像头取流推流显示前端延迟大 传统方法是服务器取摄像头的rtsp流 然后客户端连服务器 中转多了,延迟一定不小。 假设相机没有专网 公网 1相机自带推流 直接推送到云服务器 然后客户端拉去 2相机只有rtsp ,边缘服务器拉流推送到云服务器 …...
CentOS 7.9安装Nginx1.24.0时报 checking for LuaJIT 2.x ... not found
Nginx1.24编译时,报LuaJIT2.x错误, configuring additional modules adding module in /www/server/nginx/src/ngx_devel_kit ngx_devel_kit was configured adding module in /www/server/nginx/src/lua_nginx_module checking for LuaJIT 2.x ... not…...
