百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

Qt小项目:贪吃蛇游戏_qq版贪吃蛇

liebian365 2025-02-18 12:17 2 浏览 0 评论

Qt小项目贪吃蛇游戏,主要掌握定时器、信号与槽、按键事件、绘制事件、坐标运算、随机数生成等。

QWidget 绘制界面

widget.h


```cpp
#ifndef WIDGET_H
#define WIDGET_H


#include 
#include 


#include 
#include 
#include 
#include 


#include 
#include 


QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

// 蛇方向
typedef enum direct {
    dir_UP,
    dir_DOWN,
    dir_LEFT,
    dir_RIGHT
}dir_t;




class Widget : public QWidget
{
    Q_OBJECT


public:
    Widget(QWidget *parent = nullptr);
    ~Widget();


private:
    void topAddRect();
    void deleteLast();
    void downAddRect();
    void leftAddRect();
    void rightAddRect();


    void addFood();


    bool  checkHit();


protected:
    // 按键按压处理
    void keyPressEvent(QKeyEvent *event);
    void paintEvent(QPaintEvent *event);


private Q_SLOTS:
    void my_timeout();


private:
    Ui::Widget *ui;


    int moveFlag = dir_t::dir_UP;
    bool gameStart = false;


    QTimer *timer;
    const int startTime = 100;


    // 贪吃蛇
    QListsnakeList;


    // 贪吃蛇小方块
    const int  nodeWidth = 20;
    const  int  nodeHeight = 20;


    // 食物
    QRectF food;


};
#endif // WIDGET_H


```

若大家觉得看文章不过瘾,可以来拿Qt开发资料包,给大家整理了一个教程合集(内含:Qt C++基础,控件、布局管理、Qt框架、QML、Opencv、qt线程,,Qt界面开发,Qt网络,Qt数据库编程,Qt项目实战等),还有配套课件资料给大家哦。↓↓↓见下图↓↓↓↓

widget.cpp


```cpp
#include "widget.h"
#include "ui_widget.h"


// 三个方块代码蛇,最上面的第一个和最后面的一个通过按键进行交替删除 即snake[0]永远表示头




Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->setWindowTitle("贪吃蛇疯子");
    this->setWindowIcon(QIcon(":/icons/title.jpg"));


    qDebug()<<"x = "<x()<<" y = "<y()<<" height = "<height()<<" width = "<width();


    timer = new QTimer();
    connect(timer, &QTimer::timeout, this , &Widget::my_timeout);


    // 初始化蛇身子 3个方块
    QRectF rect(this->width()/2,this->height()/2,nodeWidth,nodeHeight);
    snakeList.append(rect);
    topAddRect();
    topAddRect();


   // 添加食物
   addFood();
}


Widget::~Widget()
{
    delete ui;
}


// 增加一个方块 左上和右下确认一个方块坐标系
void Widget::topAddRect()
{
    QPointF leftTop;                // 左上角坐标
    QPointF rightBottom;       // 右上角坐标


    if (snakeList[0].y()  <=  0) {
        // 当蛇移动到窗口顶部:确认新坐标 y = 窗口高度 - 蛇方块高度
        leftTop = QPointF(snakeList[0].x(), this->height() - nodeHeight);
        rightBottom  = QPointF(snakeList[0].x() + nodeWidth , this->height());
    }
    else {
        // 向上移动:y坐标必然减少 减少的右下角坐标为之前的下一个方块的右上角坐标
        leftTop = QPointF(snakeList[0].x(), snakeList[0].y() - nodeHeight);
        rightBottom = snakeList[0].topRight();
    }


    // 插入矩形小方块1个,由于采用的是List链表,这是典型的前插,追加
    snakeList.insert(0,QRectF(leftTop,rightBottom));
}


void Widget::downAddRect()
{
    QPointF leftTop;                // 左上角坐标
    QPointF rightBottom;       // 右上角坐标


    if (snakeList[0].y() > this->height() - nodeHeight) {
        // 当蛇移动到窗口底部:确认新坐标 y = 0
        leftTop = QPointF(snakeList[0].x(), 0);
        rightBottom  = QPointF(snakeList[0].x() + nodeWidth, 0 + nodeHeight);
    }
    else {
        // 向下移动:y坐标必然增加
        leftTop = QPointF(snakeList[0].x(), snakeList[0].y() + nodeHeight);
        rightBottom = snakeList[0].bottomRight() + QPointF(0,nodeHeight);
    }


    // 插入矩形小方块1个
    snakeList.insert(0,QRectF(leftTop,rightBottom));
}


void Widget::leftAddRect()
{
    QPointF leftTop;                // 左上角坐标
    QPointF rightBottom;       // 右上角坐标


    if (snakeList[0].x() <= 0) {
        // 当蛇移动到窗口最左部:确认新坐标 x = 窗口宽度 - 小方块宽度
        leftTop = QPointF(this->width() - nodeWidth, snakeList[0].y());
    }
    else {
        // 向左移动:x坐标必然减少
        leftTop = QPointF(snakeList[0].x() - nodeWidth, snakeList[0].y());
    }


    // 右下角坐标 = 之前一个的左上角坐标x,y + 小方块的宽高
    rightBottom  = leftTop + QPointF(nodeWidth, nodeHeight);


    // 插入矩形小方块1个
    snakeList.insert(0,QRectF(leftTop,rightBottom));
}


void Widget::rightAddRect()
{
    QPointF leftTop;                // 左上角坐标
    QPointF rightBottom;       // 右上角坐标


    if (snakeList[0].x() + nodeWidth > this->width()) {
        // 当蛇移动到窗口最右部:确认新坐标 x  = 0
        leftTop = QPointF(0, snakeList[0].y());
    }
    else {
        // 向右移动:x坐标必然增加
        leftTop = QPointF(snakeList[0].x() + nodeWidth, snakeList[0].y());
    }


    // 右下角坐标 = 之前一个的左上角坐标x,y + 小方块的宽高
    rightBottom  = leftTop + QPointF(nodeWidth, nodeHeight);


    // 插入矩形小方块1个
    snakeList.insert(0,QRectF(leftTop,rightBottom));
}


// 删除蛇身最后一个
void Widget::deleteLast()
{
    snakeList.removeLast();
}


// 食物是随机出现的
void Widget::addFood()
{
    int rectX = (qrand() % (this->width() / 20)) * 20;
    int rectY = (qrand() % (this->height() / 20)) * 20;


    // 控制小球出现的范围
    if (rectX >= 0 && rectY>=0) {
         food = QRectF(rectX, rectY, nodeWidth, nodeHeight);
         qDebug()<<"food = "<key()) {
    case Qt::Key::Key_Up:
        if (moveFlag != dir_DOWN) {
            moveFlag = dir_UP;
        }
        break;
    case Qt::Key::Key_Down:
         if (moveFlag != dir_UP) {
            moveFlag = dir_DOWN ;
         }
        break;
    case Qt::Key::Key_Left:
        if (moveFlag != dir_RIGHT) {
            moveFlag = dir_LEFT;
        }
        break;
    case Qt::Key::Key_Right:
        if (moveFlag != dir_LEFT) {
            moveFlag = dir_RIGHT;
        }
        break;
    case Qt::Key_Space:
        if (gameStart == false) {
            gameStart = true;
            timer->start(startTime); // 100ms
        }
        else {
            gameStart = false;
            timer->stop();
        }
        break;
    default:
        break;
    }
}


void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    QPen pen;
    QBrush brush;


    QPixmap pix;
    // 绘制图片背景
    pix.load(":/icons/bg_snake.png");
    painter.drawPixmap(0,0,this->width(),this->height(),pix);


    // 绘制蛇
    pen.setColor(Qt::color0);
    brush.setColor(Qt::darkGreen);          // 绿色
    brush.setStyle(Qt::SolidPattern);       // 实线图案
    painter.setPen(pen);
    painter.setBrush(brush);


    for (int i = 0; i < snakeList.length(); i++) {
        painter.drawRect(snakeList[i]);
    }
    // 分数
    ui->label_score->setText(QString::number(snakeList.length() -3));


    // 绘制食物
    painter.drawEllipse(food);


    // 蛇头碰到蛇身结束游戏
    if (checkHit()) {
       QFont font("方正舒体",30,QFont::ExtraLight,false);
       painter.setFont(font);
       painter.drawText((this->width() - 200)/2,this->height()/2,QString("游戏结束"));


        timer->stop();
    }




    QWidget::paintEvent(event);


}


// 定时器槽函数
void Widget::my_timeout()
{
    //int count = 1;  // 采用这种方式也可以加长蛇身,不过我还是喜欢我的烂方法


    // 判断蛇是否吃到食物 是否重合[交叉;相交;贯穿;横穿;横断]  蛇变长
    if (snakeList[0].intersects(food)) {
        qDebug()<<"吃到食物 snakeList[0] = "<知识拓展

QTimer

QTimer是Qt中用于定时器操作的类,它提供了一些常用的函数来控制和管理定时器的运行。下面是一些常用的QTimer函数的简介:

  • 1. `start(int msec)`: 启动定时器,以指定的毫秒数为间隔触发定时器的timeout()信号。
  • 2. `stop()`: 停止定时器,不再触发timeout()信号。
  • 3. `setInterval(int msec)`: 设置定时器的间隔时间,以毫秒为单位。
  • 4. `interval()`: 获取当前定时器的间隔时间。
  • 5. `isActive()`: 判断定时器是否处于活动状态,即是否正在运行。
  • 6. `setSingleShot(bool singleShot)`: 设置定时器的运行模式,如果设置为true,则定时器只触发一次;如果设置为false(默认值),则定时器会一直触发。
  • 7. `singleShot(int msec, const QObject* receiver, const char* member)`: 创建一个单次触发的定时器,指定触发时间、接收信号的对象和相应的槽函数。
  • 8. `remainingTime()`: 获取定时器剩余的触发时间,以毫秒为单位。

这些函数提供了基本的定时器操作功能,可以配合定时器的信号timeout()以及连接(Qt的信号与槽机制)来实现所需的定时操作。

QKeyEvent

QKeyEvent是Qt中用于处理键盘事件的类,它提供了一些常用的函数来获取和处理键盘事件的相关信息。下面是一些常用的QKeyEvent函数的简介:

  • 1. `key()`: 获取触发键盘事件的按键的Qt键盘码,返回一个Qt::Key枚举值。
  • 2. `text()`: 获取触发键盘事件的按键对应的文字,返回一个QString。
  • 3. `modifiers()`: 获取触发键盘事件时的修饰键状态,返回一个Qt::KeyboardModifiers枚举值,可用于检查Shift、Ctrl、Alt等修饰键的状态。
  • 4. `isAutoRepeat()`: 判断触发键盘事件的按键是否是自动重复的按下事件。
  • 5. `count()`: 获取自动重复按键连续触发的次数。
  • 6. `nativeVirtualKey()`: 获取底层平台的虚拟键码,返回一个int值。
  • 7. `nativeModifiers()`: 获取底层平台的修饰键状态,返回一个int值。

这些函数可以帮助你获取与键盘事件相关的信息,例如获取按下的键是哪个键,是否同时按下了修饰键,以及自动重复事件的次数等。你可以使用这些函数来处理键盘事件并根据需要执行相应的操作。

QRectF

QRectF是Qt中用于表示浮点数精度的矩形区域的类,它提供了一些常用的函数来操作和管理矩形区域。下面是一些常用的QRectF函数的简介:

  • 1. `QRectF()`: 默认构造函数,创建一个无效的矩形区域。
  • 2. `QRectF(qreal x, qreal y, qreal width, qreal height)`: 构造函数,创建一个以给定坐标、宽度和高度定义的矩形区域。
  • 3. `setRect(qreal x, qreal y, qreal width, qreal height)`: 设置矩形区域的位置和尺寸。
  • 4. `setCoords(qreal x1, qreal y1, qreal x2, qreal y2)`: 设置矩形区域的左上角和右下角的坐标。
  • 5. `x()`, `y()`, `width()`, `height()`: 获取矩形区域的左上角的x和y坐标,以及宽度和高度。
  • 6. `left()`, `top()`, `right()`, `bottom()`: 获取矩形区域的左、上、右、下边界的坐标。
  • 7. `setX(qreal x)`, `setY(qreal y)`, `setWidth(qreal width)`, `setHeight(qreal height)`: 设置矩形区域的左上角的x和y坐标,以及宽度和高度。
  • 8. `setLeft(qreal left)`, `setTop(qreal top)`, `setRight(qreal right)`, `setBottom(qreal bottom)`: 设置矩形区域的左、上、右、下边界的坐标。
  • 9. `moveTo(qreal x, qreal y)`: 移动矩形区域的位置,将其左上角设置为给定坐标。
  • 10. `translated(qreal dx, qreal dy)`: 平移矩形区域,沿x和y方向分别平移给定的距离。
  • 11. `contains(const QPointF &point)`: 判断矩形区域是否包含给定的点。
  • 12. `isEmpty()`: 判断矩形区域是否为空,即宽度或高度是否为0。
  • 13. `isNull()`: 判断矩形区域是否为空,即宽度和高度是否为0。

QPointF

QPointF是Qt中用于表示浮点数精度的二维点的类,它提供了一些常用的函数来操作和管理点的坐标。下面是一些常用的QPointF函数的简介:

  • 1. `QPointF()`: 默认构造函数,创建一个具有零值坐标的点。
  • 2. `QPointF(qreal x, qreal y)`: 构造函数,创建一个具有给定坐标的点。
  • 3. `setX(qreal x)`, `setY(qreal y)`: 设置点的x和y坐标。
  • 4. `x()`, `y()`: 获取点的x和y坐标。
  • 5. `isNull()`: 判断点是否为空,即坐标是否为零值。
  • 6. `manhattanLength()`: 计算点到坐标原点的曼哈顿距离(绝对值之和)。
  • 7. `distanceToLine(const QLineF &line)`: 计算点到给定直线的距离。
  • 8. `distanceToPoint(const QPointF &point)`: 计算点到给定点的距离。
  • 9. `operator==(const QPointF &p1, const QPointF &p2)`: 判断两个点是否相等。
  • 10. `operator!=(const QPointF &p1, const QPointF &p2)`: 判断两个点是否不相等。
  • 11. `isNull(const QPointF &point)`: 判断给定点是否为空,即坐标是否为零值。

这些函数提供了对点的基本操作,包括设置坐标、获取坐标、判断点是否为空、计算与其他点或直线的距离等。你可以使用这些函数来创建、修改和计算点的坐标,以满足你的需求。

QPainter

QPainter是Qt提供的一个用于绘图的类,它封装了绘制图形、图像以及文本的功能。下面是一些常用的QPainter函数的简介:

  • 1. `begin(QPaintDevice *device)`: 开始在给定的绘图设备上进行绘制,device可以是QWidget、QImage等。
  • 2. `end()`: 结束绘制操作。
  • 3. `setPen(const QPen &pen)`: 设置绘制的画笔,用于定义线条的样式、颜色等属性。
  • 4. `setBrush(const QBrush &brush)`: 设置绘制的刷子,用于填充封闭图形的颜色、渐变等属性。
  • 5. `setRenderHint(RenderHint hint, bool on = true)`: 开启或关闭绘制的渲染提示,例如抗锯齿、文本反锯齿等。
  • 6. `drawLine(const QLine &line)`: 绘制直线。
  • 7. `drawRect(const QRect &rect)`: 绘制矩形。
  • 8. `drawEllipse(const QRect &rect)`: 绘制椭圆。
  • 9. `drawText(const QPointF &pos, const QString &text)`: 在给定点位置绘制文本。
  • 10. `drawPixmap(const QRectF &targetRect, const QPixmap &pixmap)`: 在给定矩形区域绘制像素图。
  • 11. `save()`, `restore()`: 保存和恢复绘图状态,用于实现绘制状态的切换、叠加效果等。
  • 12. `resetTransform()`: 重置坐标变换矩阵。
  • 13. `translate(qreal dx, qreal dy)`: 平移画笔的原点。
  • 14. `scale(qreal sx, qreal sy)`: 缩放画笔,按比例调整绘图。
  • 15. `rotate(qreal angle)`: 旋转画笔,围绕原点进行旋转。

这些函数提供了绘制基本图形、文本和图像的能力,通过设置画笔、刷子和渲染提示等属性,可以实现不同样式的绘制效果。同时,你还可以使用平移、缩放和旋转等变换函数来改变画笔的绘制位置和方向。使用这些函数,你可以实现各种绘图需求,创建出丰富多样的用户界面。

QIcon

QIcon是Qt提供的一个用于管理图标的类,它可以加载、显示和操作图标。下面是一些常用的QIcon函数的简介:

  • 1. `QIcon()`: 默认构造函数,创建一个空的图标。
  • 2. `QIcon(const QString &filename)`: 构造函数,根据给定的文件名加载图标。
  • 3. `QIcon(const QPixmap &pixmap)`: 构造函数,根据给定的像素图创建图标。
  • 4. `QIcon(const QIcon &other)`: 拷贝构造函数,创建一个与给定图标相同的拷贝。
  • 5. `addFile(const QString &filename, const QSize &size = QSize(), QIcon::Mode mode = QIcon::Normal, QIcon::State state = QIcon::Off)`: 添加一个图像文件到图标中,可以指定图像的大小、模式和状态。
  • 6. `isNull()`: 判断图标是否为空,即没有加载任何图像。
  • 7. `pixmap(const QSize &size, QIcon::Mode mode = QIcon::Normal, QIcon::State state = QIcon::Off) const`: 获取图标的像素图,可以指定图像的大小、模式和状态。
  • 8. `paint(QPainter *painter, const QRect &rect, Qt::Alignment alignment = Qt::AlignCenter, QIcon::Mode mode = QIcon::Normal, QIcon::State state = QIcon::Off) const`: 在给定的矩形区域内绘制图标,可以指定对齐方式、模式和状态。
  • 9. `operator=(const QIcon &other)`: 赋值运算符,将给定图标的内容复制到当前图标。
  • 10. `operator==`, `operator!=`: 用于比较两个图标是否相等或不相等。

这些函数提供了加载、显示和操作图标的功能,你可以根据需要加载图像文件,设置图标的大小、模式和状态,绘制图标到指定的区域,并进行图标的比较和赋值操作。QIcon类在Qt中广泛用于界面开发,它使得图标的管理和使用变得简单和

相关推荐

4万多吨豪华游轮遇险 竟是因为这个原因……

(观察者网讯)4.7万吨豪华游轮搁浅,竟是因为油量太低?据观察者网此前报道,挪威游轮“维京天空”号上周六(23日)在挪威近海发生引擎故障搁浅。船上载有1300多人,其中28人受伤住院。经过数天的调...

“菜鸟黑客”必用兵器之“渗透测试篇二”

"菜鸟黑客"必用兵器之"渗透测试篇二"上篇文章主要针对伙伴们对"渗透测试"应该如何学习?"渗透测试"的基本流程?本篇文章继续上次的分享,接着介绍一下黑客们常用的渗透测试工具有哪些?以及用实验环境让大家...

科幻春晚丨《震动羽翼说“Hello”》两万年星间飞行,探测器对地球的最终告白

作者|藤井太洋译者|祝力新【编者按】2021年科幻春晚的最后一篇小说,来自大家喜爱的日本科幻作家藤井太洋。小说将视角放在一颗太空探测器上,延续了他一贯的浪漫风格。...

麦子陪你做作业(二):KEGG通路数据库的正确打开姿势

作者:麦子KEGG是通路数据库中最庞大的,涵盖基因组网络信息,主要注释基因的功能和调控关系。当我们选到了合适的候选分子,单变量研究也已做完,接着研究机制的时便可使用到它。你需要了解你的分子目前已有哪些...

知存科技王绍迪:突破存储墙瓶颈,详解存算一体架构优势

智东西(公众号:zhidxcom)编辑|韦世玮智东西6月5日消息,近日,在落幕不久的GTIC2021嵌入式AI创新峰会上,知存科技CEO王绍迪博士以《存算一体AI芯片:AIoT设备的算力新选择》...

每日新闻播报(September 14)_每日新闻播报英文

AnOscarstatuestandscoveredwithplasticduringpreparationsleadinguptothe87thAcademyAward...

香港新巴城巴开放实时到站数据 供科技界研发使用

中新网3月22日电据香港《明报》报道,香港特区政府致力推动智慧城市,鼓励公私营机构开放数据,以便科技界研发使用。香港运输署21日与新巴及城巴(两巴)公司签署谅解备忘录,两巴将于2019年第3季度,开...

5款不容错过的APP: Red Bull Alert,Flipagram,WifiMapper

本周有不少非常出色的app推出,鸵鸟电台做了一个小合集。亮相本周榜单的有WifiMapper's安卓版的app,其中包含了RedBull的一款新型闹钟,还有一款可爱的怪物主题益智游戏。一起来看看我...

Qt动画效果展示_qt显示图片

今天在这篇博文中,主要实践Qt动画,做一个实例来讲解Qt动画使用,其界面如下图所示(由于没有录制为gif动画图片,所以请各位下载查看效果):该程序使用应用程序单窗口,主窗口继承于QMainWindow...

如何从0到1设计实现一门自己的脚本语言

作者:dong...

三年级语文上册 仿写句子 需要的直接下载打印吧

描写秋天的好句好段1.秋天来了,山野变成了美丽的图画。苹果露出红红的脸庞,梨树挂起金黄的灯笼,高粱举起了燃烧的火把。大雁在天空一会儿写“人”字,一会儿写“一”字。2.花园里,菊花争奇斗艳,红的似火,粉...

C++|那些一看就很简洁、优雅、经典的小代码段

目录0等概率随机洗牌:1大小写转换2字符串复制...

二年级上册语文必考句子仿写,家长打印,孩子照着练

二年级上册语文必考句子仿写,家长打印,孩子照着练。具体如下:...

一年级语文上 句子专项练习(可打印)

...

亲自上阵!C++ 大佬深度“剧透”:C++26 将如何在代码生成上对抗 Rust?

...

取消回复欢迎 发表评论: