1. 程式人生 > 實用技巧 >Demo_2:Qt實現猜字小遊戲

Demo_2:Qt實現猜字小遊戲

1 環境

系統:windows 10

程式碼編寫執行環境:Qt Creator 4.4.1 (community)

Github:

2 簡介

參考視訊:https://www.bilibili.com/video/BV1XW411x7NU?p=35https://www.bilibili.com/video/BV1XW411x7NU?p=35

參考部落格:https://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程式碼:

 #ifndef WIDGET_H
#define WIDGET_H #include <QWidget>
#include <QString>
#include <QTimer>
#include <QMovie> namespace Ui {
class Widget;
} //目的:實現一個猜字遊戲
//說明:
// class Widget : public QWidget
{
Q_OBJECT public:
explicit Widget(QWidget *parent = );
~Widget(); //槽函式
void on_PushButtonStart_clicked();
void on_PushButtonQuit_clicked();
void on_PushButtonRollback_clicked();
void on_PushButtonNotice_clicked();
void dealNum();
void timerEvent(QTimerEvent *event); private:
int gameTime;
int gameTimerId; //遊戲定時器
int loseTimerId; //輸了
int winTimerId; //贏了
QString randStr; //隨機數
QString resultStr; //結果數
QMovie winMovie; //贏了的動畫
QMovie loseMovie; //輸了的動畫 private:
Ui::Widget *ui;
}; #endif // WIDGET_H

widget.cpp程式碼:

 #include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QTime>
#include <QMessageBox> Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this); //顯示第一個頁面,設定頁面
ui->stackedWidget->setCurrentWidget(ui->pageSet);
//失敗動畫
loseMovie.setFileName(":/new/prefix1/image/over.gif");
ui->label_lose->setMovie(&loseMovie);//給標籤設定動畫
ui->label_lose->setScaledContents(true);//讓動畫自動適應標籤大小
//勝利動畫
winMovie.setFileName(":/new/prefix1/image/win.gif");
ui->label_win->setMovie(&winMovie);
ui->label_win->setScaledContents(true); //啟動遊戲
connect(ui->pushButton_enter, &QPushButton::clicked, this, &Widget::on_PushButtonStart_clicked);
//退出遊戲
connect(ui->pushButton_quit, &QPushButton::clicked, this, &Widget::close);
//刪除前一個數字
connect(ui->pushButton_rollback, &QPushButton::clicked, this, &Widget::on_PushButtonRollback_clicked);
//提示
connect(ui->pushButton_notice, &QPushButton::clicked, this, &Widget::on_PushButtonNotice_clicked); //對數字按鈕的處理使用同一個槽函式
connect(ui->pushButton_0, &QPushButton::clicked, this, &Widget::dealNum);
connect(ui->pushButton_1, &QPushButton::clicked, this, &Widget::dealNum);
connect(ui->pushButton_2, &QPushButton::clicked, this, &Widget::dealNum);
connect(ui->pushButton_3, &QPushButton::clicked, this, &Widget::dealNum);
connect(ui->pushButton_4, &QPushButton::clicked, this, &Widget::dealNum);
connect(ui->pushButton_5, &QPushButton::clicked, this, &Widget::dealNum);
connect(ui->pushButton_6, &QPushButton::clicked, this, &Widget::dealNum);
connect(ui->pushButton_7, &QPushButton::clicked, this, &Widget::dealNum);
connect(ui->pushButton_8, &QPushButton::clicked, this, &Widget::dealNum);
connect(ui->pushButton_9, &QPushButton::clicked, this, &Widget::dealNum);
} void Widget::on_PushButtonStart_clicked()
{
//獲取下拉框時間,並將字串轉換為整數
gameTime = ui->comboBox->currentText().toInt();
qDebug() << gameTime << "s"; //切換到遊戲介面
ui->stackedWidget->setCurrentWidget(ui->pageGame); int num;
//從0時0分0秒到現在的秒數為種子
qsrand(QTime(, , ).secsTo(QTime::currentTime()));
//呼叫全域性的qsrand()函式生成隨機數,對10000取餘,保證位於10000的範圍內
while((num = qrand()%) < );
randStr = QString::number(num);
qDebug() << "randNum" << randStr; //設定進度條
ui->progressBar->setMinimum(); //最小值
ui->progressBar->setMaximum(gameTime); //最大值
ui->progressBar->setValue(gameTime); //當前值 //啟動定時器
gameTimerId = startTimer(); //以1000ms為間隔
resultStr.clear();
ui->textEdit->clear();
} void Widget::on_PushButtonRollback_clicked()
{
//退格按鈕,刪除最後一個數字
if(resultStr.size() == ) {
resultStr.clear();
ui->textEdit->clear();
} else {
resultStr.chop(); //截斷最後一位字元
ui->textEdit->setText(resultStr);
}
} void Widget::on_PushButtonNotice_clicked()
{
//提示
resultStr.clear();
QString str = "正確答案為:" + randStr;
ui->textEdit->setText(str);
} void Widget::timerEvent(QTimerEvent *event)
{
if(event->timerId() == gameTimerId) { //遊戲時間
gameTime--;
//設定進度條
ui->progressBar->setValue(gameTime); //當前值
//時間到
if( == gameTime) {
//關閉定時器
killTimer(gameTimerId);
QMessageBox::information(this, "失敗", "時間到了啊!!!");
loseMovie.start();//啟動動畫
//切換失敗動畫頁面
ui->stackedWidget->setCurrentWidget(ui->pageLose);
loseTimerId = startTimer(); //啟動定時器
}
} else if(event->timerId() == loseTimerId) { //失敗動畫時間
//停止動畫,停止定時器,回到遊戲設定頁面
loseMovie.stop();//停止動畫
killTimer(loseTimerId); //停止定時器
//切換到遊戲設定頁面
ui->stackedWidget->setCurrentWidget(ui->pageSet);
} else if(event->timerId() == winTimerId) { //勝利動畫時間
winMovie.stop();//停止動畫
killTimer(winTimerId); //停止定時器
//切換到遊戲設定頁面
ui->stackedWidget->setCurrentWidget(ui->pageSet);
}
} void Widget::dealNum()
{
//獲取訊號傳送者
QObject *mysender = sender();
//轉換為按鈕型別
QPushButton *pb = (QPushButton *)mysender;
if (NULL != pb) {
//獲取按鈕內容
QString numStr = pb->text();
resultStr += numStr;
//數字不能以0開始
if (resultStr.size() == && resultStr=="") {
resultStr.clear();
}
//保證顯示結果為4位
if(resultStr.size() <= ) {
ui->textEdit->setText(resultStr);
if (resultStr.size() == ) {
if (resultStr > randStr) {
ui->textEdit->append("數字大了點!!!");
} else if (resultStr < randStr) {
ui->textEdit->append("數字小了點!!!");
} else {
ui->textEdit->append("恭喜你答對了!!!");
//停止定時器
killTimer(gameTimerId);
QMessageBox::information(this, "勝利", "恭喜你!!!");
//啟動win頁面
winMovie.start();
ui->stackedWidget->setCurrentWidget(ui->pageWin);
//啟動定時器
winTimerId = startTimer(); //5s
}
//初始化字串結果,清空
resultStr.clear();
}
}
}
} Widget::~Widget()
{
delete ui;
}

4 總結

主要有以下問題可能實現的時候會遇到:

(1)佈局

佈局這個確實不好弄,我也不太熟悉,當佈局時最好先把相關聯的元件放在一個Widget裡面布好局之後,再進行全體佈局。

(2)按鈕的字型設定在QWidget類裡面,而不是在QAbstractButton裡。

(3)程式碼中,定時器我們是使用的定時器事件處理函式timerEvent()來做的,而不是訊號與槽。

如果程式碼中還有其它問題,希望網友指出來。