Demo_2:Qt實現猜字小遊戲
1 環境
系統:windows 10
代碼編寫運行環境:Qt Creator 4.4.1 (community)
Github:
2 簡介
參考視頻://www.bilibili.com/video/BV1XW411x7NU?p=35//www.bilibili.com/video/BV1XW411x7NU?p=35
參考博客://blog.csdn.net/fengge2018/article/details/106411326
實現功能:一個猜字小遊戲,系統隨機產生一個4位數,在規定時間內,我們輸入4位數進行匹配,如果相同,則贏了;不同且時間到了,則輸了。
贏了的實現效果如下:
輸了的實現效果如下:
3 實現過程
下面簡單說明一下實現的過程:
(1)先創建一個帶ui的項目工程,主要包含了如下文件。
(2)ui界面的設計
我們進入widget.ui進行界面設計。使用QStackWidget來存放多個頁面,包括以下4個頁面:
pageSet是我們剛開始運行時的頁面,包含兩個QLabel、一個QComboBox、兩個QPushButton,如下圖:
pageGame是我們玩遊戲時的頁面,包含一個QProgressBar、一個QTextEdit、10個按鈕,如下圖:
pageWin是勝利時顯示的頁面,就只包含一個QLabel組件:
pageLose是輸了的時候顯示的頁面,也只包含一個QLabel組件:
(3)代碼邏輯
啟動後,我們點擊「進入遊戲按鈕」切換到pageGame,並讀取出QComboBox中設置的倒計時時間,啟動一個計數器開始計數,並生成一個四位數的隨機數;
然後我們輸入數字按鈕開始進行匹配,數字按鈕的槽函數使用同一個,因為它們處理的邏輯是一樣的;
若我們輸入的數字和隨機數相同,則計數器停止計數,並切換到pageWin,啟動另一個計時器,顯示5s動畫後,回到pageSet;
若我們輸入的數字和隨機數不同,則判斷其和隨機數的大小,並給出對應的提示;
若時間到了且我們沒有猜出成功的答案,則切換到pageLose,啟動另一個計時器,顯示5s動畫後,回到pageSet。
(4)實現代碼
widget.h代碼:


1 #ifndef WIDGET_H 2 #define WIDGET_H 3 4 #include <QWidget> 5 #include <QString> 6 #include <QTimer> 7 #include <QMovie> 8 9 namespace Ui { 10 class Widget; 11 } 12 13 //目的:實現一個猜字遊戲 14 //說明: 15 // 16 17 class Widget : public QWidget 18 { 19 Q_OBJECT 20 21 public: 22 explicit Widget(QWidget *parent = 0); 23 ~Widget(); 24 25 //槽函數 26 void on_PushButtonStart_clicked(); 27 void on_PushButtonQuit_clicked(); 28 void on_PushButtonRollback_clicked(); 29 void on_PushButtonNotice_clicked(); 30 void dealNum(); 31 void timerEvent(QTimerEvent *event); 32 33 private: 34 int gameTime; 35 int gameTimerId; //遊戲定時器 36 int loseTimerId; //輸了 37 int winTimerId; //贏了 38 QString randStr; //隨機數 39 QString resultStr; //結果數 40 QMovie winMovie; //贏了的動畫 41 QMovie loseMovie; //輸了的動畫 42 43 44 private: 45 Ui::Widget *ui; 46 }; 47 48 #endif // WIDGET_H
View Code
widget.cpp代碼:


1 #include "widget.h" 2 #include "ui_widget.h" 3 #include <QDebug> 4 #include <QTime> 5 #include <QMessageBox> 6 7 Widget::Widget(QWidget *parent) : 8 QWidget(parent), 9 ui(new Ui::Widget) 10 { 11 ui->setupUi(this); 12 13 //顯示第一個頁面,設置頁面 14 ui->stackedWidget->setCurrentWidget(ui->pageSet); 15 //失敗動畫 16 loseMovie.setFileName(":/new/prefix1/image/over.gif"); 17 ui->label_lose->setMovie(&loseMovie);//給標籤設置動畫 18 ui->label_lose->setScaledContents(true);//讓動畫自動適應標籤大小 19 //勝利動畫 20 winMovie.setFileName(":/new/prefix1/image/win.gif"); 21 ui->label_win->setMovie(&winMovie); 22 ui->label_win->setScaledContents(true); 23 24 //啟動遊戲 25 connect(ui->pushButton_enter, &QPushButton::clicked, this, &Widget::on_PushButtonStart_clicked); 26 //退出遊戲 27 connect(ui->pushButton_quit, &QPushButton::clicked, this, &Widget::close); 28 //刪除前一個數字 29 connect(ui->pushButton_rollback, &QPushButton::clicked, this, &Widget::on_PushButtonRollback_clicked); 30 //提示 31 connect(ui->pushButton_notice, &QPushButton::clicked, this, &Widget::on_PushButtonNotice_clicked); 32 33 //對數字按鈕的處理使用同一個槽函數 34 connect(ui->pushButton_0, &QPushButton::clicked, this, &Widget::dealNum); 35 connect(ui->pushButton_1, &QPushButton::clicked, this, &Widget::dealNum); 36 connect(ui->pushButton_2, &QPushButton::clicked, this, &Widget::dealNum); 37 connect(ui->pushButton_3, &QPushButton::clicked, this, &Widget::dealNum); 38 connect(ui->pushButton_4, &QPushButton::clicked, this, &Widget::dealNum); 39 connect(ui->pushButton_5, &QPushButton::clicked, this, &Widget::dealNum); 40 connect(ui->pushButton_6, &QPushButton::clicked, this, &Widget::dealNum); 41 connect(ui->pushButton_7, &QPushButton::clicked, this, &Widget::dealNum); 42 connect(ui->pushButton_8, &QPushButton::clicked, this, &Widget::dealNum); 43 connect(ui->pushButton_9, &QPushButton::clicked, this, &Widget::dealNum); 44 } 45 46 void Widget::on_PushButtonStart_clicked() 47 { 48 //獲取下拉框時間,並將字符串轉換為整數 49 gameTime = ui->comboBox->currentText().toInt(); 50 qDebug() << gameTime << "s"; 51 52 //切換到遊戲界面 53 ui->stackedWidget->setCurrentWidget(ui->pageGame); 54 55 int num; 56 //從0時0分0秒到現在的秒數為種子 57 qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime())); 58 //調用全局的qsrand()函數生成隨機數,對10000取余,保證位於10000的範圍內 59 while((num = qrand()%10000) < 999); 60 randStr = QString::number(num); 61 qDebug() << "randNum" << randStr; 62 63 //設置進度條 64 ui->progressBar->setMinimum(0); //最小值 65 ui->progressBar->setMaximum(gameTime); //最大值 66 ui->progressBar->setValue(gameTime); //當前值 67 68 //啟動定時器 69 gameTimerId = startTimer(1000); //以1000ms為間隔 70 resultStr.clear(); 71 ui->textEdit->clear(); 72 } 73 74 void Widget::on_PushButtonRollback_clicked() 75 { 76 //退格按鈕,刪除最後一個數字 77 if(resultStr.size() == 1) { 78 resultStr.clear(); 79 ui->textEdit->clear(); 80 } else { 81 resultStr.chop(1); //截斷最後一位字符 82 ui->textEdit->setText(resultStr); 83 } 84 } 85 86 void Widget::on_PushButtonNotice_clicked() 87 { 88 //提示 89 resultStr.clear(); 90 QString str = "正確答案為:" + randStr; 91 ui->textEdit->setText(str); 92 } 93 94 void Widget::timerEvent(QTimerEvent *event) 95 { 96 if(event->timerId() == gameTimerId) { //遊戲時間 97 gameTime--; 98 //設置進度條 99 ui->progressBar->setValue(gameTime); //當前值 100 //時間到 101 if(0 == gameTime) { 102 //關閉定時器 103 killTimer(gameTimerId); 104 QMessageBox::information(this, "失敗", "時間到了啊!!!"); 105 loseMovie.start();//啟動動畫 106 //切換失敗動畫頁面 107 ui->stackedWidget->setCurrentWidget(ui->pageLose); 108 loseTimerId = startTimer(5000); //啟動定時器 109 } 110 } else if(event->timerId() == loseTimerId) { //失敗動畫時間 111 //停止動畫,停止定時器,回到遊戲設置頁面 112 loseMovie.stop();//停止動畫 113 killTimer(loseTimerId); //停止定時器 114 //切換到遊戲設置頁面 115 ui->stackedWidget->setCurrentWidget(ui->pageSet); 116 } else if(event->timerId() == winTimerId) { //勝利動畫時間 117 winMovie.stop();//停止動畫 118 killTimer(winTimerId); //停止定時器 119 //切換到遊戲設置頁面 120 ui->stackedWidget->setCurrentWidget(ui->pageSet); 121 } 122 } 123 124 void Widget::dealNum() 125 { 126 //獲取信號發送者 127 QObject *mysender = sender(); 128 //轉換為按鈕類型 129 QPushButton *pb = (QPushButton *)mysender; 130 if (NULL != pb) { 131 //獲取按鈕內容 132 QString numStr = pb->text(); 133 resultStr += numStr; 134 //數字不能以0開始 135 if (resultStr.size() == 1 && resultStr=="0") { 136 resultStr.clear(); 137 } 138 //保證顯示結果為4位 139 if(resultStr.size() <= 4) { 140 ui->textEdit->setText(resultStr); 141 if (resultStr.size() == 4) { 142 if (resultStr > randStr) { 143 ui->textEdit->append("數字大了點!!!"); 144 } else if (resultStr < randStr) { 145 ui->textEdit->append("數字小了點!!!"); 146 } else { 147 ui->textEdit->append("恭喜你答對了!!!"); 148 //停止定時器 149 killTimer(gameTimerId); 150 QMessageBox::information(this, "勝利", "恭喜你!!!"); 151 //啟動win頁面 152 winMovie.start(); 153 ui->stackedWidget->setCurrentWidget(ui->pageWin); 154 //啟動定時器 155 winTimerId = startTimer(5000); //5s 156 } 157 //初始化字符串結果,清空 158 resultStr.clear(); 159 } 160 } 161 } 162 } 163 164 Widget::~Widget() 165 { 166 delete ui; 167 }
View Code
4 總結
主要有以下問題可能實現的時候會遇到:
(1)布局
布局這個確實不好弄,我也不太熟悉,當布局時最好先把相關聯的組件放在一個Widget裏面布好局之後,再進行全體布局。
(2)按鈕的字體設置在QWidget類裏面,而不是在QAbstractButton里。
(3)代碼中,定時器我們是使用的定時器事件處理函數timerEvent()來做的,而不是信號與槽。
如果代碼中還有其它問題,希望網友指出來。