QT项目实战:贪吃蛇小游戏

目录

内容介绍

一.添加头文件

二.初始化蛇与奖品

三.设置背景图,蛇与奖品

1.设置背景图

2.画蛇

3.画奖品

四.小蛇移动

1.控制方向

2.向上移动

3.向下移动

4.向右移动

5.向左移动

五.随机生成奖品位置

六.是否吃到奖品

七.删除操作

八.游戏结束

九.效果演示

十.代码演示

.h

.cpp


内容介绍

首先,在构造函数中,创建了一个定时器,并设置了信号和槽的连接,这样定时器每次超时时间到达,就会调用timeout函数。同时,在构造函数中也创建了蛇和奖品,并将它们画在了界面上。

在keyPressEvent函数中,根据用户按下的方向键,来改变蛇的移动方向。

在addTop、addDown、addRight、addLeft函数中,根据蛇的当前移动方向,来生成蛇的新身体部分,并插入到蛇的身体列表的最前面。

在addNewReward函数中,生成一个新的奖品,并将它的位置记录在rewardNode变量中。

在paintEvent函数中,使用QPainter来画出背景、蛇和奖品,并判断蛇是否与奖品或者自己的身体发生了碰撞,如果发生了碰撞,则游戏结束。

在deleteLast函数中,删除蛇的最后一节身体。

在checkContact函数中,判断蛇的身体是否发生了重合,如果发生了重合,则返回true,否则返回false。

在timeout函数中,根据蛇的当前移动方向,生成新的身体部分,并插入到蛇的身体列表的最前面,同时判断蛇的头部是否碰到了奖品,如果碰到了,则增长蛇的身体,并生成一个新的奖品,如果蛇的身体发生了重合,则游戏结束。

一.添加头文件

#include <QKeyEvent> 是 C++ 源代码文件中包含 Qt 库的头文件,用于处理键盘事件。在应用程序中,可以通过重写 QWidget::keyPressEvent() 或 QWidget::keyReleaseEvent() 函数来处理键盘事件。这两个函数的参数都是 QKeyEvent 对象,可以用它来获取键盘事件的详细信息,例如按下或释放的键、键的序号、修饰键等。

#include <QTimer> 是 C++ 源代码文件中包含 Qt 库的头文件,用于创建定时器。QTimer 是 Qt 中用于定时操作的类,可以用来触发特定时间间隔后的操作。通过 QTimer,可以实现定时执行某些任务、定时更新界面等功能。

#include <QPainter> 是 C++ 源代码文件中包含 Qt 库的头文件,用于绘制图形和图像。QPainter 是 Qt 中用于绘制图形和图像的类,可以用来绘制各种形状、文本、图像等。通过 QPainter,可以实现自定义绘制、图形界面美化等功能。

二.初始化蛇与奖品

三.设置背景图,蛇与奖品

1.设置背景图

    QPixmap pix;pix.load("D://3.jpg");painter.drawPixmap(0,0,600,368,pix);

2.画蛇

创建了一个 QPainter 对象 painter,并设置了画笔颜色为黑色、画刷颜色为深紫色,填充方式为实心填充。然后,将画笔和画刷设置到 painter 对象中。最后,遍历 snake 数组,绘制每个矩形。

3.画奖品

首先设置了画笔颜色为红色、画刷颜色为深紫色,填充方式为实心填充。然后,将画笔和画刷设置到 painter 对象中。接着,绘制了一个奖品圆形。如果 checkContact() 函数返回 true,则表示与奖品接触,此时会设置字体为方正舒体,大小为30,加粗,斜体,并绘制游戏结束提示信息。最后,停止计时器,并调用父类的 paintEvent() 函数。

四.小蛇移动

1.控制方向

(1).定义一个 QKeyEvent 指针 event,用于接收键盘事件。

(2).使用 switch 语句根据 event->key() 返回的键值进行不同的操作。

如果按下的是 Qt::Key_Up 键,则判断当前移动方向 moveFlag 是否为 DIR_DOWN,如果不是,则将 moveFlag 设置为 DIR_UP。
如果按下的是 Qt::Key_Down 键,则判断当前移动方向 moveFlag 是否为 DIR_UP,如果不是,则将 moveFlag 设置为 DIR_DOWN。
如果按下的是 Qt::Key_Left 键,则判断当前移动方向 moveFlag 是否为 DIR_RIGHT,如果不是,则将 moveFlag 设置为 DIR_LEFT。
如果按下的是 Qt::Key_Right 键,则判断当前移动方向 moveFlag 是否为 DIR_LEFT,如果不是,则将 moveFlag 设置为 DIR_RIGHT。
如果按下的是 Qt::Key_Space 键,则判断游戏是否已经开始,如果未开始,则将 gameStart 设置为 true,启动定时器 timer,并设置定时器的时间间隔为 time;如果游戏已经开始,则将 gameStart 设置为 false,停止定时器 timer。
如果按下的是其他键,则不做任何操作。

2.向上移动

小蛇向上移动可以看做将最下面的方块删除,在最上方增加一个方块,实现小蛇向上移动。其他方向依照这种逻辑即可。

3.向下移动

4.向右移动

5.向左移动

五.随机生成奖品位置

六.是否吃到奖品

1.定义一个整型变量 count,初始化为 1。

2.判断蛇的第一个节点 snake[0] 是否与食物 rewardNode 重合,如果重合,则 count 加 1,调用 addNewReward() 函数添加新的食物。

3.使用 while 循环 count 次,根据当前移动方向 moveFlag 的值,分别调用 addTop()addDown()addLeft()addRight() 函数,添加新的蛇节点。

4.调用 deleteLast() 函数删除蛇的最后一个节点。

5.调用 update() 函数更新界面。

七.删除操作

八.游戏结束

检查蛇身是否相撞,标准游戏结束

九.效果演示

十.代码演示

.h

#ifndef WIDGET_H
#define WIDGET_H
#include <QKeyEvent>
#include <QWidget>
#include <QTimer>
#include <QPainter>namespace Ui {
class Widget;
}typedef enum Direct{DIR_LEFT,DIR_RIGHT,DIR_UP,DIR_DOWN
}dir_t;class Widget : public QWidget
{Q_OBJECTpublic:explicit Widget(QWidget *parent = nullptr);~Widget();protected:void keyPressEvent(QKeyEvent *event);void addTop();void addDown();void addRight();void addLeft();void addNewReward();void paintEvent(QPaintEvent *event);void deleteLast();bool checkContact();private:Ui::Widget *ui;dir_t moveFlag = DIR_UP;bool gameStart = false;QTimer *timer;int time = 100;//超时时间间隔//奖品QRectF rewardNode;//蛇QList <QRectF> snake;//小方块的高度int nodeWidth = 20;int nodeHeight = 20;protected slots://定时器void timeout();};#endif // WIDGET_H

.cpp

#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);//使用定时器timer = new QTimer();//信号槽connect(timer,SIGNAL(timeout()),this,SLOT(timeout()));resize(600,368);//初始化蛇身子QRectF rect(300,180,nodeHeight,nodeWidth);snake.append(rect);addTop();addTop();//初始化奖品addNewReward();
}Widget::~Widget()
{delete ui;
}//控制方向
void Widget::keyPressEvent(QKeyEvent *event)
{switch (event->key()) {case Qt::Key_Up:if(moveFlag != DIR_DOWN){moveFlag = DIR_UP;}break;case Qt::Key_Down:if(moveFlag != DIR_UP){moveFlag = DIR_DOWN;}break;case Qt::Key_Left:if(moveFlag != DIR_RIGHT){moveFlag = DIR_LEFT;}break;case Qt::Key_Right:if(moveFlag != DIR_LEFT){moveFlag = DIR_RIGHT;}break;case Qt::Key_Space:if(gameStart == false){gameStart = true;//启动定时器timer->start(time);}else{gameStart = false;timer->stop();}break;default:break;}
}void Widget::addTop()
{QPointF leftTop;QPointF rightBotom;if(snake[0].y() - nodeHeight < 0){leftTop = QPointF(snake[0].x() , this->height() - nodeHeight);rightBotom = QPointF(snake[0].x() + nodeWidth , 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() + nodeWidth , nodeHeight);}else{leftTop = snake[0].bottomLeft();rightBotom = snake[0].bottomRight() + QPointF(0,nodeHeight);}snake.insert(0,QRectF(leftTop,rightBotom));
}void Widget::addRight()
{QPointF leftTop;QPointF rightBotom;if(snake[0].x() + nodeWidth*2 > this->width()){leftTop = QPointF(0,snake[0].y());}else{leftTop = snake[0].topRight();}rightBotom = leftTop + QPointF(nodeWidth,nodeHeight);snake.insert(0,QRectF(leftTop,rightBotom));
}void Widget::addLeft()
{QPointF leftTop;QPointF rightBotom;if(snake[0].x() - nodeWidth < 0){leftTop = QPointF(this->width() - nodeWidth , snake[0].y());}else{leftTop = snake[0].topLeft() - QPointF(nodeWidth,0);}rightBotom = leftTop + QPointF(nodeWidth,nodeHeight);snake.insert(0,QRectF(leftTop,rightBotom));
}void Widget::addNewReward()
{rewardNode = QRectF(qrand()%(this->width()/20) * 20,qrand()%(this->height()/20) * 20,nodeHeight,nodeWidth);
}void Widget::paintEvent(QPaintEvent *event)
{QPainter painter(this);QPen pen;QBrush brush;//背景图QPixmap pix;pix.load("D://3.jpg");painter.drawPixmap(0,0,600,368,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::darkMagenta);brush.setStyle(Qt::SolidPattern);painter.setPen(pen);painter.setBrush(brush);painter.drawEllipse(rewardNode);if(checkContact()){QFont font("方正舒体",30,QFont::ExtraLight,false);painter.setFont(font);painter.drawText((this->width()-300)/2,(this->height()-30)/2,QString("GAME OVER"));timer->stop();}QWidget::paintEvent(event);
}void Widget::deleteLast()
{snake.removeLast();
}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;
}void Widget::timeout()
{int count = 1;//判断是否有重合if(snake[0].intersects(rewardNode)){count++;addNewReward();}while (count--) {switch (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();
}

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

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

相关文章

Android:基于Gradle 7.0+(8.2、8.6)发布aar到maven仓库,使用maven-publish插件

maven插件与maven-publish插件的区别 maven插件适用于gradle1.0-6.2版本&#xff0c;6.2版本后该插件就被废弃了&#xff0c;推荐使用maven-publish插件。 maven-publis插件是在gradle 1.3 版本后开始支持的&#xff0c;使配置更加简洁。 maven-publis插件的使用 砍柴不误磨…

数据结构:二叉树的序列化和反序列化(序列和二叉树结构一一对应)

文章目录 一、基础知识1.1 序列化和反序列基础知识1.2 string与int转化STL函数 二、详解说明2.1 基于前序遍历的序列化和反序列化2.2 基于后序遍历的序列化和反序列化2.3 基于层序遍历的序列化和反序列化 三、例题——652. 寻找重复的子树 三个相同题目&#xff1a; 297. 二叉树…

Pencils Protocol Season 2 收官在即,Season 3 携系列重磅权益来袭

此前Scroll生态LaunchPad &聚合收益平台Pencils Protocol&#xff08;原Penpad&#xff09;&#xff0c;推出了首个资产即其生态代币PDD的Launch&#xff0c;Season 2活动主要是用户通过质押ETH代币、组件战队等方式&#xff0c;来获得Point奖励&#xff0c;并以该Point为依…

C++那些事之Mixin惯用法

C那些事之Mixin惯用法 大家好&#xff0c;我是光城&#xff0c;今天给大家分享C那些事里面的一个惯用法&#xff1a;mixin 混合&#xff08;Mixins&#xff09;是Lisp中的一个概念。混合是类的一部分&#xff0c;意味着它旨在与其他类或混合组合在一起。常规独立类&#xff08;…

C++学习~~string类

1.STL简单介绍 &#xff08;1&#xff09;标准模版库&#xff0c;是C里面的标准库的一部分&#xff0c;C标准库里面还有其他的东西&#xff0c;但是我们不经常使用&#xff0c;我们经常使用的还是STL这个标准库部分。 &#xff08;2&#xff09;六大件&#xff1a;仿函数&…

内网安全工具之ADExplorer的使用

ADExplorer是域内一款信息查询工具&#xff0c;它是独立的可执行文件&#xff0c;无需安装。它能够列出域组织架构、用户账号、计算机账号登&#xff0c;可以帮助寻找特权用户和数据库服务器等敏感目标。 下载地址&#xff1a;http://live.sysinternals.com/ 连接 下载了ADE…

SSM宠物管理系统-计算机毕业设计源码56932

摘 要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针对宠物管理系统等问题&#xff0c;对宠物管理…

使用Docker在阿里云ECS上部署Gitlab,提供代码托管、CICD 和 docker镜像服务

文章目录 使用Docker在阿里云ECS上部署Gitlab1.购买一个数据&#xff0c;挂载到/data用于存储gitlab相关数据2. 部署docker引擎3. 调整ssh的默认端口&#xff0c;将22端口留给gitlab4. 部署gitlab5. 进入docker容器获取gitlab的默认密码6. 登录gitlab&#xff0c;完成gitlab-ru…

Spring Boot代码案例(计算器、登录、留言板)

文章目录 一、计算器二、登录2.1 判断账号密码是否正确2.2 根据不同的用户作出不同反应 三、留言板3.1 提交数据3.2 展示所有数据 四、Lombok 工具包4.1 场景介绍4.2 如何使用 五、Edit Starters插件六、项目如何Debug七、项目命名规范 一、计算器 导入前端文件后端代码&#…

Risk Of Rain 雨中冒险2服务器开服联机教程

1、购买后登录服务器&#xff08;百度莱卡云&#xff09; 1.1、第一次购买服务器会安装游戏端&#xff0c;大约5分钟左右&#xff0c;如果长时间处于安装状态请联系客服 2、设置游戏端口 由于雨中冒险2的设置需要两个端口&#xff0c;它们用于游戏端口&#xff0c;查询端口&am…

理解 Python 中的 `super()` 与 `__init__()` 方法

在 Python 的面向对象编程中&#xff0c;super() 函数和 __init__() 方法是两个非常重要的概念。它们在类的继承和初始化过程中扮演着关键的角色。本文将深入探讨这两个概念的工作原理&#xff0c;并通过示例代码来展示它们的使用。 基本原理 __init__() 方法 __init__() 是…

K8S认证 | CKA题库 + 答案 | 查看Pod CPU资源使用量

2、查看集群中运行Pod CPU资源使用量 您必须在以下Cluster/Node上完成此考题&#xff1a; Cluster Master node Worker node k8s …