【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.rhkb.cn/news/250431.html

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

相关文章

yum命令下载出现Failed to synchronize cache for repo ‘AppStream‘, ignoring this repo.

修改下面的配置文件 问题&#xff1a; cd /etc/yum.repos.d 修改下面四个文件 vim CentOS-Base.repo vim CentOS-AppStream.repo vim CentOS-Extras.repo vim CentOS-PowerTools.repo测试yum是否正常 yum -y install wget

Linux 高并发服务器

多进程并发服务器 使用多进程并发服务器时要考虑以下几点&#xff1a; 父进程最大文件描述个数(父进程中需要close关闭accept返回的新文件描述符)系统内创建进程个数(与内存大小相关)进程创建过多是否降低整体服务性能(进程调度) server /* server.c */ #include <stdio…

8.DNS域名解析服务器

目录 1. 概述 1.1. 产生原因 1.2. 作用&#xff1a; 1.3. 连接方式 1.4. 因特网的域名结构 1.4.1. 拓扑&#xff1a; 1.4.2. 分类 1.4.3. 域名服务器类型划分 2. DNS域名解析过程 2.1. 分类&#xff1a; 2.2. 解析图&#xff1a; 2.2.1. 图&#xff1a; 2.2.2. 过…

Entity实体设计

Entity实体设计 &#x1f4a1;用来和数据库中的表对应&#xff0c;解决的是数据格式在Java和数据库间的转换。 &#xff08;一&#xff09;设计思想 数据库Java表类行对象字段&#xff08;列&#xff09;属性 &#xff08;二&#xff09;实体Entity编程 编码规范 &#x1f4a…

IDEA JDBC配置

一、在pom中添加依赖 <dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency></dependencies> 然后同步一下 二、编写代码…

Ubuntu18.04安装Matlab流程笔记

提示:博主取舍了很多大佬的博文并亲测有效,分享笔记邀大家共同学习讨论 Ubuntu18.04 安装Matlab流程 下载安装包和破解文件安装Matlab注册并运行 下载安装包和破解文件 matlabR2019A源码 提取码:2ztb 下载的Linux matlab2018a文件夹内有三个文件&#xff1a; # 解压Matlab201…

vue-3d-model

vue-3d-model - npm GitHub - hujiulong/vue-3d-model: &#x1f4f7; vue.js 3D model viewer component 通过该插件降低Threejs的使用难度 vue项目加载三维模型&#xff0c;我把模型放在了服务器的tomcat里面&#xff0c;需要对tomcat的fbx项目文件夹设置跨域&#xff0c;如…

关于破解IDEA后启动闪退的问题

问题描述&#xff1a;2023.1启动不了&#xff0c;双击桌面图标&#xff0c;没有响应。 解决办法&#xff1a; 打开C:\Users\c\AppData\Roaming\JetBrains\IntelliJIdea2023.1\idea64.exe.vmoptions 这个文件。 内容如下所示&#xff1a; 删除红框的数据以后&#xff0c;再登录…

算法41:掉落的方块(力扣699题)----线段树

题目&#xff1a;https://leetcode.cn/problems/falling-squares/description/ 在二维平面上的 x 轴上&#xff0c;放置着一些方块。 给你一个二维整数数组 positions &#xff0c;其中 positions[i] [lefti, sideLengthi] 表示&#xff1a;第 i 个方块边长为 sideLengthi &…

Docker 阿里云镜像仓库CR使用实践

一、使用容器镜像&#xff0c;查看镜像&#xff0c;创建&#xff0c;推送&#xff0c;拉取阿里云镜像 CR镜像管理&#xff08;阿里云容器镜像服务&#xff08;Container Registry&#xff09;&#xff09; 登录实例 未创建的镜像名称也可以push、docker的私有仓库需要提起创建…

[.NET] 查询当前已安装所有 Win32 与 UWP 应用

为了获取当前设备用户已安装的所有应用程序, 一般来讲有两种方案. 一种是通过查询 “shell:AppsFolder” 目录下所有项, 一种是从开始菜单中获取所有快捷方式, 然后加上查询所有已安装的 UWP 应用, 最后得到总列表. 如需代码参考, 请看 github.com/SlimeNull/WindowsAppsQuery …

基于Web停车场管理系统

技术架构&#xff1a; Spring MVC JSP MySQL 有需要该项目的小伙伴可以私信我你的Q。 功能描述&#xff1a; 基于Web停车场管理系统主要用于实现停车场相关信息管理&#xff0c;基本功能包括&#xff1a;系统信息管理模块、车位信息管理模块、IC卡信息管理模块、固定车主…

【PaddleSpeech】语音合成-男声

环境安装 系统&#xff1a;Ubuntu > 16.04 源码下载 使用apt安装 build-essential sudo apt install build-essential 克隆 PaddleSpeech 仓库 # github下载 git clone https://github.com/PaddlePaddle/PaddleSpeech.git # 也可以从gitee下载 git clone https://gite…

后端软件三层架构

一、三层架构简介 三层架构是软件开发中广泛采用的一种经典架构模式&#xff0c;其核心价值在于通过清晰的任务划分来提高代码的可维护性和重用性。具体来说&#xff0c;三层架构主要包括以下三个层次&#xff1a; 持久层&#xff08;DAO层&#xff09;&#xff1a;这一层主要…

设备的层次结构 - 驱动程序的复杂层次结构

由于设备对象的水平结构和垂直结构&#xff0c;组成了Windows设备的树形结构图。在Windows中出事的时候会有一个根设备&#xff0c;为了理解简单&#xff0c;我们将PCI总线想象成根总线&#xff08;根总线其实不是PCI总线&#xff0c;只是为了理解方便&#xff09;。查到PCI总线…

京东物流基于 StarRocks 的数据分析平台建设

作者&#xff1a;京东物流 数据专家 刘敬斌 小编导读&#xff1a; 京东集团 2007 年开始自建物流&#xff0c;2017 年 4 月正式成立京东物流集团&#xff0c;截至目前&#xff0c;京东物流已经构建了一套全面的智能物流系统&#xff0c;实现服务自动化、运营数字化及决策智能化…

基于WordPress开发微信小程序1:搭建Wordpress

2年前&#xff0c;在知乎上提问&#xff1a;多数公司为什么宁愿自研也不用wordpress二次开发建站&#xff1f; - 知乎 (zhihu.com)&#xff0c;收到了&#xff0c;很多回答 自己打算做一下提升&#xff0c;便有了自己基于wordpress开发微信小程序的想法 项目定位 基于wordpre…

项目安全-----加密算法实现

目录 对称加密算法 AES &#xff08;ECB模式&#xff09; AES(CBC 模式)。 非对称加密 对称加密算法 对称加密算法&#xff0c;是使用相同的密钥进行加密和解密。使用对称加密算法来加密双方的通信的话&#xff0c;双方需要先约定一个密钥&#xff0c;加密方才能加密&#…

SpringBoot实战2

目录 1.如何返回两个类型的数据&#xff1f;User和Booth 2.如何使用MyBatis遍历一个数组进行查询&#xff1f; 3.前端要的数据太多太杂&#xff0c;我们拼接多个List&#xff0c;前端找数据困难&#xff0c;浪费时间。因此我们进行三表联表查询。 1.首先创建一个vo包&#x…

用Python和 Cryptography库给你的文件加密解密

用Python和 Cryptography库给你的文件加密解密 用Python和 Cryptography库给你的文件加把安全锁。 先介绍与加密解密有关的几个基本概念。 加密&#xff08;Encryption&#xff09;&#xff1a;加密是将明文转换为密文的过程&#xff0c;使得未经授权的人无法读懂。 解密&a…