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学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...

NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行
项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战,克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的
修改bug思路: 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑:async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...

Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...

破解路内监管盲区:免布线低位视频桩重塑停车管理新标准
城市路内停车管理常因行道树遮挡、高位设备盲区等问题,导致车牌识别率低、逃费率高,传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法,正成为破局关键。该设备安装于车位侧方0.5-0.7米高度,直接规避树枝遮…...

【LeetCode】算法详解#6 ---除自身以外数组的乘积
1.题目介绍 给定一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O…...

渗透实战PortSwigger靶场:lab13存储型DOM XSS详解
进来是需要留言的,先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码,输入的<>当成字符串处理回显到页面中,看来只是把用户输…...