【QT】贪吃蛇小游戏 -- 童年回忆

成品展示

项目分析:
🐍基本元素如下

🐍小蛇的设计,初始大小蛇头占一个方块,蛇身占两个方块。
🐍关于小蛇的移动,采用蛇头前进方向增加一个方块,蛇尾减掉一个方块的实现方法。
🐍在移动过程中不能立即向前进反方向移动(如正在向左前进的小蛇,按下向右的按键应当无效果),当小蛇吃到食物后,蛇身自增,并记录得分。
🐍当小蛇碰到边界处 或 自身时游戏结束。
🐍食物随机生成。

工程创建

游戏背景图片准备

小游戏的设计采用的是“穿越方案”,到达边界后会从另一边出现。并未设置墙壁碰撞检测。下图墙壁仅为图片,在代码实现过程中可根据需求添加碰撞检测。

主体框架预览

主要函数分析

按键处理

void Widget::keyPressEvent(QKeyEvent* event)
{switch(event->key()){case Qt::Key_Up:if(this->moveFlag != DIR_DOWN){this->moveFlag = DIR_UP;}break;case Qt::Key_Down:if(this->moveFlag != DIR_UP){this->moveFlag = DIR_DOWN;}break;case Qt::Key_Right:if(this->moveFlag != DIR_LEFT){this->moveFlag = DIR_RIGHT;}break;case Qt::Key_Left:if(this->moveFlag != DIR_RIGHT){this->moveFlag = DIR_LEFT;}break;case Qt::Key_Space:if(this->gameStart == false){this->gameStart = true;//游戏开始,启动定时器this->timer->start(TIME);}else{this->gameStart = false;this->timer->stop();}break;default:break;}
}

渲染绘图

//渲染
void Widget::paintEvent(QPaintEvent* et)
{QPainter painter(this);QPen pen;QBrush brush;//背景图片QPixmap pix;pix.load("D:/snake/snake_b1.png");painter.drawPixmap(0,0,820,460,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]);}//画 食物pen.setColor(Qt::red);brush.setColor(Qt::red);brush.setStyle(Qt::SolidPattern);painter.setPen(pen);painter.setBrush(brush);painter.drawEllipse(this->rewardNode);//绘制得分QFont font("方正舒体",17,QFont::ExtraLight,false);painter.setFont(font);painter.drawText((this->width() - 75),this->height()- 427, QString::number(this->score));if(checkContact()){painter.drawText((this->width() - 300)/2,(this->height()-30)/2,QString("小蛇不小心咬到了自己,游戏结束!!!"));this->timer->stop();}QWidget::paintEvent(et);
}

槽函数

void Widget::timeout()
{int count = 1;//蛇头是否 触碰到食物if(snake[0].intersects(this->rewardNode)){addNewReword();score++;count++;}while(count--){switch(this->moveFlag){case DIR_UP://蛇上方加方格addTop();break;case DIR_DOWN://蛇下方加方格addDown();break;case DIR_LEFT://蛇左边加空格addLeft();break;case DIR_RIGHT://蛇右边加空格addRight();break;default:break;}}//删除尾部方块deleteLast();update();
}

蛇运动

以向上运动为例:

情况1:蛇头运动越界,从另一端“穿越”回游戏界面。

情况2:正常运动

运动实现原理:

向上增加方块,代码实现:

void Widget::addTop()
{QPointF leftTop;//左上QPointF rightBotom;//右下//方案1:如果越界(蛇头碰到墙体) -- 游戏失败//方案2:穿墙(上越界,从下边界出来)if(snake[0].y() - NODEHEIGHT < 0){//方案1:游戏直接结束//方案2:穿墙leftTop = QPoint(snake[0].x(),this->height() - NODEHEIGHT);rightBotom = QPoint(snake[0].x()+NODEHEIGHT,this->height());}else{//正常增加方块leftTop = QPointF(snake[0].x(),snake[0].y()-NODEHEIGHT);rightBotom = snake[0].topRight();}snake.insert(0,QRectF(leftTop,rightBotom));
}

整体代码   

widget.h

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QList>
#include <Qtime>
QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACEtypedef enum DIR
{DIR_LEFT,DIR_RIGHT,DIR_UP,DIR_DOWN
}dir_t;//超时时间 单位毫秒
#define TIME 100
#define NODEHEIGHT 20//y轴边界
#define BORDER_X 300
//x轴边界
#define BORDER_Y 500class Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();//槽函数
protected slots://定时器启动 触发该槽函数void timeout();
protected://上 -- 蛇身增长void addTop();//下 -- 蛇身增长void addDown();//左 -- 蛇身增长void addRight();//右 -- 蛇身增长void addLeft();//删除蛇尾方块void deleteLast();//随机生成食物void addNewReword();//渲染void paintEvent(QPaintEvent* event);//蛇头碰到蛇身判断bool checkContact();//按键处理 -- 重写void keyPressEvent(QKeyEvent* event);
private:Ui::Widget *ui;//记录当前头部朝向int moveFlag = DIR_UP;//游戏是否开始bool gameStart = false;//记录蛇身体QList<QRectF> snake;//定时器QTimer* timer;//食物QRectF rewardNode;//积分int score;
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QKeyEvent>
#include <QTimer>
#include <QPainter>
#include <QPaintEvent>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//初始化定时器this->timer = new QTimer();//信号和槽connect(timer,SIGNAL( timeout() ),this,SLOT( timeout() ));//调整窗口带下this->resize(820,460);//初始化蛇身QPointF leftTop = QPointF(200,200);QPointF rightBotom = QPointF(220,220);snake.insert(0,QRectF(leftTop,rightBotom));//初始化食物addNewReword();//初始化积分this->score = 0;addTop();addTop();
}Widget::~Widget()
{delete ui;
}void Widget::keyPressEvent(QKeyEvent* event)
{switch(event->key()){case Qt::Key_Up:if(this->moveFlag != DIR_DOWN){this->moveFlag = DIR_UP;}break;case Qt::Key_Down:if(this->moveFlag != DIR_UP){this->moveFlag = DIR_DOWN;}break;case Qt::Key_Right:if(this->moveFlag != DIR_LEFT){this->moveFlag = DIR_RIGHT;}break;case Qt::Key_Left:if(this->moveFlag != DIR_RIGHT){this->moveFlag = DIR_LEFT;}break;case Qt::Key_Space:if(this->gameStart == false){this->gameStart = true;//游戏开始,启动定时器this->timer->start(TIME);}else{this->gameStart = false;this->timer->stop();}break;default:break;}
}//渲染
void Widget::paintEvent(QPaintEvent* et)
{QPainter painter(this);QPen pen;QBrush brush;//背景图片QPixmap pix;pix.load("D:/snake/snake_b1.png");painter.drawPixmap(0,0,820,460,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]);}//画 食物pen.setColor(Qt::red);brush.setColor(Qt::red);brush.setStyle(Qt::SolidPattern);painter.setPen(pen);painter.setBrush(brush);painter.drawEllipse(this->rewardNode);//绘制得分QFont font("方正舒体",17,QFont::ExtraLight,false);painter.setFont(font);painter.drawText((this->width() - 75),this->height()- 427, QString::number(this->score));if(checkContact()){painter.drawText((this->width() - 300)/2,(this->height()-30)/2,QString("小蛇不小心咬到了自己,游戏结束!!!"));this->timer->stop();}QWidget::paintEvent(et);
}void Widget::addTop()
{QPointF leftTop;//左上QPointF rightBotom;//右下//方案1:如果越界(蛇头碰到墙体) -- 游戏失败//方案2:穿墙(上越界,从下边界出来)if(snake[0].y() - NODEHEIGHT < 0){//方案1:游戏直接结束//方案2:穿墙leftTop = QPoint(snake[0].x(),this->height() - NODEHEIGHT);rightBotom = QPoint(snake[0].x()+NODEHEIGHT,this->height());}else{//正常增加方块leftTop = QPointF(snake[0].x(),snake[0].y()-NODEHEIGHT);rightBotom = snake[0].topRight();}snake.insert(0,QRectF(leftTop,rightBotom));
}
//向下增加方块
void Widget::addDown()
{QPointF leftTop;QPointF rightBotom;if(snake[0].y() + NODEHEIGHT*2 > this->height())//越界{//修正坐标leftTop = QPointF(snake[0].x(),0);rightBotom = QPointF(snake[0].x()+NODEHEIGHT,NODEHEIGHT);}else{//leftTop = snake[0].bottomLeft();rightBotom = snake[0].bottomRight() + QPointF(0,NODEHEIGHT);}snake.insert(0,QRectF(leftTop,rightBotom));
}
void Widget::addLeft()
{QPointF leftTop;QPointF rightBotom;if(snake[0].x() - NODEHEIGHT < 0)//越界{//修正坐标leftTop = QPointF(this->width()-NODEHEIGHT,snake[0].y());}else{leftTop = snake[0].topLeft() - QPointF(NODEHEIGHT,0);}rightBotom = leftTop + QPointF(NODEHEIGHT,NODEHEIGHT);snake.insert(0,QRectF(leftTop,rightBotom));
}
void Widget::addRight()
{QPointF leftTop;QPointF rightBotom;if(snake[0].x() + NODEHEIGHT*2 > this->width())//越界{//修正坐标leftTop = QPointF(0,snake[0].y());}else{//leftTop = snake[0].topRight();}rightBotom = leftTop + QPointF(NODEHEIGHT,NODEHEIGHT);snake.insert(0,QRectF(leftTop,rightBotom));
}void Widget::deleteLast()
{snake.removeLast();
}void Widget::timeout()
{int count = 1;//蛇头是否 触碰到食物if(snake[0].intersects(this->rewardNode)){addNewReword();score++;count++;}while(count--){switch(this->moveFlag){case DIR_UP://蛇上方加方格addTop();break;case DIR_DOWN://蛇下方加方格addDown();break;case DIR_LEFT://蛇左边加空格addLeft();break;case DIR_RIGHT://蛇右边加空格addRight();break;default:break;}}//删除尾部方块deleteLast();update();
}
//随机生成食物
void Widget::addNewReword()
{rewardNode = QRectF(qrand()%(this->width()/20) * 20,qrand()% (this->height()/20) * 20,NODEHEIGHT,NODEHEIGHT);
}bool Widget::checkContact()
{for(int i = 0;i<snake.length();++i){for(int j = i+1;j<snake.length();++j){if(snake[i] == snake[j]){return true;}}}return false;
}

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

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

相关文章

享元模式~

“享元”我们可以理解为共享元素&#xff0c;比如我们生活中的共享单车&#xff0c;共享充电宝&#xff0c;共享汽车&#xff0c;这样做的目的就是为了提高资源的复用&#xff0c;但对于共享的单车&#xff0c;充电宝等&#xff0c;它的拥有者和创建时间是不相同的&#xff0c;…

案例九:寻找丢失的数据

在生活中我们经常会遇到误将重要的数据文件删除或误格式化U盘,今天小编带大家一块来学习将丢失的数据找回,来,首先我们这节案例要使用一个工具(R-Studio) 接下来我们一块来如何将数据恢复; 由于我们软件是英文,我们首先要将切换为中文的;‍

记一次 Android CPU高使用率排查

文章目录 背景排查高占用的进程adb shelltoptop -b -H -n 1 | grep 29337 (打印各线程 cpu使用详情)kill -3 29337 (生成trace文件)adb pull /data/anr /Users/gerry.liang/Desktop定位问题 补充说明: 背景 测试同学反馈我们的App CPU使用率 90% 居高不下,经过一番艰难的排查后…

Facebook的数字合作愿景:创新与未来发展

随着科技的飞速发展&#xff0c;Facebook一直处于数字创新的前沿&#xff0c;致力于构建开放、智能、社交的数字社交体验。本文将深入探讨Facebook的数字合作愿景&#xff0c;探索其在创新与未来发展方面的雄心壮志。 引言 在当今数字化时代&#xff0c;社交媒体不仅是人们沟通…

多线程(进阶三:JUC)

目录 一、Callable接口 1、创建线程的操作 2、编写多线程代码 &#xff08;1&#xff09;实现Runnable接口&#xff08;使用匿名内部类&#xff09; &#xff08;2&#xff09;实现Callable接口&#xff08;使用匿名内部类&#xff09; 二、ReentrantLock 1、ReentrantL…

Docker 容器卷

1、概念介绍 如果是CentOS7安全模块会比之前系统版本加强&#xff0c;不安全的会先禁止&#xff0c;所以目录挂载的情况被默认为不安全的行为&#xff0c;在SELinux里面挂载目录被禁止掉了&#xff0c;如果要开启&#xff0c;我们一般使用--privlegedtrue命令&#xff0c;扩大…

微信小程序新手入门教程三:基础语法介绍

WXML&#xff08;WeiXin Markup Language&#xff09;是框架设计的一套标签语言&#xff0c;可以与各种组件相结合&#xff0c;进行页面构建。 一 常用标签 wxml的语法结构与我们熟悉的html很像&#xff0c;但在细节处略有不同&#xff0c;我们可以参考html标签对比记忆。wxm…

面试150 位1的个数 位运算

Problem: 191. 位1的个数 文章目录 思路复杂度Code 思路 &#x1f468;‍&#x1f3eb; 参考 复杂度 Code public class Solution {// you need to treat n as an unsigned valuepublic int hammingWeight(int n){int res 0;while (n ! 0){res 1;n & n - 1;// 把最后…

python-游戏篇-初级-飞机大战

文章目录 开发环境要求运行方法代码效果 开发环境要求 本系统的软件开发及运行环境具体如下。 操作系统&#xff1a;Windows 7、Windows 10。Python版本&#xff1a;Python 3.7.1。开发工具&#xff1a;PyCharm 2018或VScode。Python内置模块&#xff1a;sys、random、codecs…

聊聊百度造车

10月27日&#xff0c;极越-01上市&#xff0c;一个月后大幅降价&#xff0c;时至今日距离发布已经过去了两个月&#xff0c;官方迟迟不肯公布销量&#xff0c;实际情况大家也都心知肚明。 如今小米汽车技术发布会风头无两&#xff0c;而同一年宣布造车的极越却无人问津&#x…

Hadoop:HDFS学习巩固——基础习题及编程实战

一 HDFS 选择题 1.对HDFS通信协议的理解错误的是&#xff1f; A.客户端与数据节点的交互是通过RPC&#xff08;Remote Procedure Call&#xff09;来实现的 B.HDFS通信协议都是构建在IoT协议基础之上的 C.名称节点和数据节点之间则使用数据节点协议进行交互 D.客户端通过一…

leetcode 28.找出字符串中第一个匹配项的下标(python版)

需求 给你两个字符串 haystack 和 needle &#xff0c;请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标&#xff08;下标从 0 开始&#xff09;。 如果 needle 不是 haystack 的一部分&#xff0c;则返回 -1 。 示例 1&#xff1a; 输入&#xff1a;haystack…

FS【2】:CAT-Net

文章目录 前言AbstractIntroductionMethodsProblem DefinitionNetwork OverviewMask Incorporated Feature ExtractionCross Masked Attention TransformerSelf-Attention ModuleCross Masked Attention ModulePrototypical Segmentation Module Iterative Refinement Framewor…

Unity | Spine动画记录

https://blog.csdn.net/linshuhe1/article/details/79792432 https://blog.csdn.net/winds_tide/article/details/128925407 1.需要的三个文件 通常制作好的 Spine 动画导出时会有三个文件&#xff1a; .png 、.json 和 .atlas&#xff1a; skeleton-name.json 或 skeleton-…

压力测试工具-Jmeter使用总结

目录 一.前言 二.线程组 三.线程组的组件 四.线程组-HTTP请求 1、JSON提取器 2、XPATH提取器 3、正则表达式提取器 五.线程组-断言 1、响应断言 2、JSON断言 六.创建测试 1.创建线程组 2.配置元件 3.构造HTTP请求 4.添加HTTP请求头 5.添加断言 6.添加查看结果树…

Mac电脑连接linux远程桌面

起因 家庭中的内网下有一台ubuntu虚拟机&#xff0c;只能通过ssh终端操作或者通过实体机进行操作实在有些不方便。所以便想着通过linux远程桌面的方式进行连接&#xff0c;由于家庭内网&#xff0c;延迟还是非常低的。 步骤 首先在ubuntu虚拟机上安装xrdp&#xff08;可能已…

Vue3下载WEBAPI导出的Excel文件

webApi查询数据保存为Excel /// <summary>/// 获取LMI3D相机涂胶测量数据/// </summary>/// <returns></returns>[HttpPost(Name "GetLMI3DGlueDataToExcel")]public async Task<IActionResult> GetLMI3DGlueDataToExcel(QueryGlueM…

基于SSM的健身房会员管理系统(有报告)。Javaee项目。ssm项目。

演示视频&#xff1a; 基于SSM的健身房会员管理系统(有报告)。Javaee项目。ssm项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring SpringMvc Mybatis J…

国货之光--数据库设计开源工具-[PDManer 元数建模 - v4]

[PDManer 元数建模 - v4]&#xff0c;历时五年&#xff0c;持续升级&#xff0c;工匠精神&#xff0c;做一款简单好用的数据库建模平台。 元数建模平台&#xff0c;使用 ReactElectronJava 技术体系构建。 [PDMan-v2] --> [CHINER-v3] --> [PDManer-v4]&#xff0c;连续五…

车载测试Vector工具CANoe——常见问题汇总(上)

车载测试Vector工具CANoe——常见问题汇总(上) 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师(Wechat:gongkenan2013)。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一…