• 【Qt】三种方式实现抽奖小游戏


    简介

    本文章是基本Qt与C++实现一个抽奖小游戏,用到的知识点在此前发布的几篇文章。
    下面是跳转链接:
    【Qt控件之QLabel】用法及技巧链接: https://blog.csdn.net/MrHHHHHH/article/details/133691441?spm=1001.2014.3001.5501

    【Qt控件之QPushButton】用法及技巧 链接:
    https://blog.csdn.net/MrHHHHHH/article/details/133692079?spm=1001.2014.3001.5501

    【Qt控件之QDialog】用法及技巧 链接:
    https://blog.csdn.net/MrHHHHHH/article/details/133721638?spm=1001.2014.3001.5501

    【Qt控件之QMainWindow】用法及技巧 链接:
    https://blog.csdn.net/MrHHHHHH/article/details/133722035?spm=1001.2014.3001.5501

    【Qt控件之QTimer】用法及技巧 链接:
    https://blog.csdn.net/MrHHHHHH/article/details/133722476?spm=1001.2014.3001.5501

    实现方式

    实现方式多种多样,但毕竟是小程序,需求明确(就没考虑操作及优化),功能简单,条理清晰,主要提供三种实现方式(此阶段未实现概率设置,之后再发布概率设置版本吧):

    1. 基于while循环
    • 示例:
      先粘贴UI
      在这里插入图片描述

    .h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include 
    
    QT_FORWARD_DECLARE_CLASS(C_DlgSetting)
    
    namespace Ui {
    class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    
    private slots:
        // 退出
        void slot_actQuit_triggered();
        // 设置概率
        void slot_actSetting_triggered();
        // 开始
        void slot_btnStart_clicked();
        // 停止
        void slot_btnStop__clicked();
    
    private:
        Ui::MainWindow *ui;
    
        C_DlgSetting*       m_pDlgSetting; // 概率设置类
    
        bool                m_bFlag = false;// 标志
    };
    
    #endif // MAINWINDOW_H
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    .cpp

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include "DlgSetting.h"
    
    #include 
    #include 
    #include 
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        // m_pDlgSetting = new C_DlgSetting(this);
    
        // 信号和槽
        {
            connect(ui->action_quit, &QAction::triggered, this, &MainWindow::slot_actQuit_triggered);
            connect(ui->action_setting, &QAction::triggered, this, &MainWindow::slot_actSetting_triggered);
            connect(ui->btn_start, &QPushButton::clicked, this, &MainWindow::slot_btnStart_clicked);
            connect(ui->btn_stop, &QPushButton::clicked, this, &MainWindow::slot_btnStop__clicked);
        }
    
        // 声明随机数种子,不然就是伪随机(每次产生的随机数都一样)
        qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    void MainWindow::slot_actQuit_triggered()
    {
        close();
    }
    
    void MainWindow::slot_actSetting_triggered()
    {
        // m_pDlgSetting->exec();
    }
    
    void MainWindow::slot_btnStart_clicked()
    {
        if(m_bFlag)
        {
            return;
        }
        QStringList sl;
        sl << "一等奖" << "二等奖" << "三等奖" << "四等奖" << "五等奖";
        m_bFlag = true;
        while (m_bFlag) {
            int nRange = qrand() % 5;
            ui->label_turn->setText(sl.at(nRange));
            // 100ms转一次
            QThread::msleep(100);
            // 防止界面卡死
            QCoreApplication::processEvents();
        }
    }
    
    void MainWindow::slot_btnStop__clicked()
    {
        m_bFlag = false;
        // 显示最终获奖结果
        QString strRes = QString("最终结果: %1").arg(ui->label_turn->text());
        ui->label_res->setText(strRes);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70

    .main

    #include "mainwindow.h"
    #include 
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
        w.show();
    
        return a.exec();
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 结果
      在这里插入图片描述
    • 实现思路
      – 设置UI,注意命名
      – 进行信号和槽连接
      – 实现"开始"和"结束"功能
      – 显示结果
    2. 基于定时器
    • 示例
      UI显示与1.是一样的,需借助QTimer实现

    QTimer 是 Qt 框架中的一个类,用于在特定的时间间隔后发出一个信号。它是 Qt
    的事件循环系统的一部分,该系统允许程序在等待某些事件(如用户输入或定时器超时)时保持响应。

    QTimer 的工作原理是将定时器的超时作为一个事件添加到 Qt
    的事件队列中。当事件循环检测到定时器超时时,它就会发出预定的信号。这种机制允许 QTimer
    在等待定时器超时时不会阻塞用户界面,因为事件循环可以继续处理其他事件,如用户输入或绘制事件。

    相比之下,如果使用标准的 C++ 定时器,如
    std::this_thread::sleep_for,在等待定时器超时时,当前线程将被阻塞,无法处理其他事件。这会导致用户界面无响应,给用户一种程序已经卡死的感觉。

    直接粘贴相关代码:
    .h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include 
    #include 
    
    namespace Ui {
    class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    
    private slots:
        // 退出
        void slot_actQuit_triggered();
        // 开始
        void slot_btnStart_clicked();
        // 停止
        void slot_btnStop__clicked();
        // 定时器处理
        void slot_timeout();
    
    private:
        Ui::MainWindow *ui;
        bool                m_bFlag = false;// 标志
    
        QTimer*             m_pTimer;// 定时器
    };
    
    #endif // MAINWINDOW_H
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    .cpp

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    #include 
    #include 
    #include 
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        m_pTimer = new QTimer(this);
        // 处理
        connect(m_pTimer, &QTimer::timeout, this, &MainWindow::slot_timeout);
    
        // 信号和槽
        {
            connect(ui->action_quit, &QAction::triggered, this, &MainWindow::slot_actQuit_triggered);
            connect(ui->btn_start, &QPushButton::clicked, this, &MainWindow::slot_btnStart_clicked);
            connect(ui->btn_stop, &QPushButton::clicked, this, &MainWindow::slot_btnStop__clicked);
        }
    
        // 声明随机数种子,不然就是伪随机(每次产生的随机数都一样)
        qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    void MainWindow::slot_actQuit_triggered()
    {
        close();
    }
    void MainWindow::slot_btnStart_clicked()
    {
    	// 此处可先判断定时器是否处于活动状态,如果是,则返回;否则,再启动
    	// ToDoSomething
    	{
    	
    	}
        m_pTimer->start(100);
    }
    
    void MainWindow::slot_btnStop__clicked()
    {
        m_pTimer->stop();
        // 显示最终获奖结果
        QString strRes = QString("最终结果: %1").arg(ui->label_turn->text());
        ui->label_res->setText(strRes);
    }
    
    void MainWindow::slot_timeout()
    {
        QStringList sl;
        sl << "一等奖" << "二等奖" << "三等奖" << "四等奖" << "五等奖";
        int nRange = qrand() % 5;
        ui->label_turn->setText(sl.at(nRange));
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 实现思路
      – 点击"开始",启动定时器
      – “定时器"实现界面刷新
      – 点击"结束”,停止定时器,并将结果显示
    3. 基于线程
    • 实现思路(等之后发布线程文章后,实现)
      – 在主窗口创建一个线程对象
      – 点击"开始",将信号发送到线程中,用于更新几等奖
      – 线程将更新后的信息发送到主窗口
      – 主窗口动态显示
      – 点击"结束",停止线程,显示结果

    go.

  • 相关阅读:
    k8s的Helm
    cmake学习笔记 一
    创建开机自启的脚本
    【吴恩达机器学习-笔记整理】大规模机器学习,随机/批量/小批量梯度下降,在线学习,数据并行
    在 IconFont 上获取图标资源的操作方法与感悟
    C++:多态
    golang pg数据库操作,insert(sql)插入一条数据后获返回当前插入数据的id --chatGPT
    CRM助力客户开发
    神经网络拟合函数表达式,神经网络拟合效果不好
    仓库库存管理系统:目的、开发和使用
  • 原文地址:https://blog.csdn.net/MrHHHHHH/article/details/133739085