1 环境
系统:windows 10
代码编写运行环境:Qt Creator 4.4.1 (community)
Github:https://github.com/zhengcixi/Qt_Demo/tree/master/GuessNum
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位数进行匹配,如果相同,则赢了;不同且时间到了,则输了。
赢了的实现效果如下:
![](https://img2020.cnblogs.com/blog/1078885/202007/1078885-20200704161143641-427070459.gif)
输了的实现效果如下:
![](https://img2020.cnblogs.com/blog/1078885/202007/1078885-20200704161335284-1110061231.gif)
3 实现过程
下面简单说明一下实现的过程:
(1)先创建一个带ui的项目工程,主要包含了如下文件。
![](https://img2020.cnblogs.com/blog/1078885/202007/1078885-20200704161605326-383842405.png)
(2)ui界面的设计
我们进入widget.ui进行界面设计。使用QStackWidget来存放多个页面,包括以下4个页面:
![](https://img2020.cnblogs.com/blog/1078885/202007/1078885-20200704161812880-1228305346.png)
pageSet是我们刚开始运行时的页面,包含两个QLabel、一个QComboBox、两个QPushButton,如下图:
![](https://img2020.cnblogs.com/blog/1078885/202007/1078885-20200704161904293-620097869.png)
pageGame是我们玩游戏时的页面,包含一个QProgressBar、一个QTextEdit、10个按钮,如下图:
![](https://img2020.cnblogs.com/blog/1078885/202007/1078885-20200704161944563-546378321.png)
pageWin是胜利时显示的页面,就只包含一个QLabel组件:
![](https://img2020.cnblogs.com/blog/1078885/202007/1078885-20200704162036217-1244662184.png)
pageLose是输了的时候显示的页面,也只包含一个QLabel组件:
![](https://img2020.cnblogs.com/blog/1078885/202007/1078885-20200704162130392-499640763.png)
(3)代码逻辑
启动后,我们点击“进入游戏按钮”切换到pageGame,并读取出QComboBox中设置的倒计时时间,启动一个计数器开始计数,并生成一个四位数的随机数;
然后我们输入数字按钮开始进行匹配,数字按钮的槽函数使用同一个,因为它们处理的逻辑是一样的;
若我们输入的数字和随机数相同,则计数器停止计数,并切换到pageWin,启动另一个计时器,显示5s动画后,回到pageSet;
若我们输入的数字和随机数不同,则判断其和随机数的大小,并给出对应的提示;
若时间到了且我们没有猜出成功的答案,则切换到pageLose,启动另一个计时器,显示5s动画后,回到pageSet。
(4)实现代码
widget.h代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #ifndef WIDGET_H
2 #define WIDGET_H
3
4 #include
5 #include
6 #include
7 #include
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代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include "widget.h"
2 #include "ui_widget.h"
3 #include
4 #include
5 #include
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() 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() 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() textEdit->setText(resultStr);
141 if (resultStr.size() == 4) {
142 if (resultStr > randStr) {
143 ui->textEdit->append("数字大了点!!!");
144 } else if (resultStr 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()来做的,而不是信号与槽。
如果代码中还有其它问题,希望网友指出来。
|