学了这么久的QT,决定使用QT写一个猜数字的小游戏来锻炼自己对QT应用。
先使用一个stackedWidget来存放两个页面,一个页面是开始页面,另一个页面是游戏页面,不得不说这个容器真的很好使用,我一开始还准备使用字父窗口来实现主界面和游戏界面的切换。
主窗口的头文件代码:
#ifndef GUESSNUM_H
#define GUESSNUM_H
#include
#include
#include"youwin.h"
#include"youloss.h"
QT_BEGIN_NAMESPACE
namespace Ui { class GuessNum; }
QT_END_NAMESPACE
class GuessNum : public QWidget
{
Q_OBJECT
public:
GuessNum(QWidget *parent = nullptr);
void timerEvent(QTimerEvent*)override;
~GuessNum();
public slots:
void close_or_not();
void openGame();
void For_button();
private slots:
void on_back_clicked();
private:
Ui::GuessNum *ui;
int GameTime;//游戏总时长
int lastTime;//剩余游戏时长
int Curtime;//触发计时器事件的间隔
QString result;//最终结果的字符串
QString The_Number_to_guess;//所需要猜的数字
youWin win_widget;//获胜的窗口
youLoss loss_widget;//失败的窗口
};
#endif // GUESSNUM_H
来说一下我遇到的一些问题,进度条的移动这个操作就是需要设置一个计时器,在点击按钮开始游戏的同时就开始计时,然后有一个时间事件函数,把timeId设置为每1000ms触发一次时间事件函数,然后时间事件函数所执行的操作是不断的对剩余时间进行自减操作,然后设定进度条的当前时间这样就可以实现进度条的移动了。还有一点需要十分注意,就是开始游戏这个按钮如果在鼠标点击的时候时间长了一点,有可能会触发两次会产生BUG,所以我们在开始游戏的按钮的槽函数中对按钮进行blockSignals(true)函数的操作来切断按钮对点击产生的信号,然后在返回主页面的时候再连接上。而我对游戏界面中的0~9所有按钮都执行的是同一个槽函数,在槽函数中使用sender()函数来获取所点击的按钮,再对返回值进行类型转换,然后获取按钮中的内容,把内容加到结果字符串上,当内容字符串到达4位的时候进行正确与否的判断,错误就清空结果字符串,正确就播放可爱的桥本环奈的动图界面并跳回主界面初始化所有数据,而且停止计时器的触发。而游戏失败是在时间事件函数中进行判断的,由于一旦猜中就会停止计时器的触发,如果计时器剩余时间等于0的时候就会直接宣布游戏失败并跳转到失败页面,同时初始化所有数据,过一会就会跳转到游戏主界面从新开始。还有对于下拉框时间的选择问题上,comboBox有一个函数可以获取选择的字符串再把字符串转换为整型数,但是我的字符串中有字母,所以不能直接转换。因此我选择使用获取下标的方法来转换获得总的游戏时间。
主窗口的实现文件代码:
#include "guessnum.h"
#include "ui_guessnum.h"
#include
#include
#include
#include
#include
#include
GuessNum::GuessNum(QWidget *parent)
: QWidget(parent)
, ui(new Ui::GuessNum)
{
ui->setupUi(this);
this->setWindowTitle("猜数字");
resize(800,400);
ui->stackedWidget->setCurrentIndex(0);
Curtime=0;
//关联上“退出游戏”按钮
connect(ui->close,&QPushButton::released,this,&GuessNum::close_or_not);
//关联上“开始游戏“按钮
connect(ui->start,&QPushButton::pressed,this,&GuessNum::openGame);
//关联上数字键盘按钮
connect(ui->play0,&QPushButton::pressed,this,&GuessNum::For_button);
connect(ui->play1,&QPushButton::pressed,this,&GuessNum::For_button);
connect(ui->play2,&QPushButton::pressed,this,&GuessNum::For_button);
connect(ui->play3,&QPushButton::pressed,this,&GuessNum::For_button);
connect(ui->play4,&QPushButton::pressed,this,&GuessNum::For_button);
connect(ui->play5,&QPushButton::pressed,this,&GuessNum::For_button);
connect(ui->play6,&QPushButton::pressed,this,&GuessNum::For_button);
connect(ui->play7,&QPushButton::pressed,this,&GuessNum::For_button);
connect(ui->play8,&QPushButton::pressed,this,&GuessNum::For_button);
connect(ui->play9,&QPushButton::pressed,this,&GuessNum::For_button);
}
GuessNum::~GuessNum()
{
delete ui;
}
void GuessNum::close_or_not()
{
int res=QMessageBox::question(this,"问题","是否退出结束游戏?");
if(res==QMessageBox::Yes)
{
this->close();
}
}
void GuessNum::openGame()
{
ui->stackedWidget->setCurrentIndex(1);
ui->start->blockSignals(true);//切断信号传递,预防多次点击
int num;
//生成随机的目标四位数
//以从0时0分0秒到现在的秒数为种子
qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
//调用全局的qrand()函数生成随机数,对10000取余,保证位于10000以内
while((num=qrand()%10000)<999);//这里的循环为了确保数字是一个四位数
The_Number_to_guess=QString::number(num);//把所获得的随机数转换为字符串
qDebug()<comboBox->currentIndex();
GameTime=60+index*10;
lastTime=GameTime;
//给进度条设定时间
ui->progressBar->setMinimum(0);
ui->progressBar->setMaximum(GameTime);
ui->progressBar->setValue(GameTime);
//qDebug()<startTimer(1000);
}
void GuessNum::timerEvent(QTimerEvent *)
{
if(lastTime==0)//当时间用尽的时候,说明挑战失败
{
this->killTimer(Curtime);
ui->textBrowser->append("游戏失败!!");
QMessageBox::about(this,"失败","很遗憾你没有在规定时间内猜出正确数字!!");
ui->textBrowser->clear();
result.clear();
The_Number_to_guess.clear();
ui->start->blockSignals(false);
//播放失败页面
loss_widget.show();
//跳转页面
ui->stackedWidget->setCurrentIndex(0);
}
else
{
lastTime--;
ui->progressBar->setValue(lastTime);
}
}
void GuessNum::For_button()
{
QObject*mySender=this->sender();//获取所点击的按钮
QPushButton*Button_Pointer=(QPushButton*)mySender;
if(Button_Pointer!=nullptr)
{
QString Button_Text=Button_Pointer->text();//获取按钮中的内容
result+=Button_Text;
if(result.size()==1&&result=="0")
{
result.clear();
}
ui->textBrowser->setText(result);
if(result.size()==4)//当位数满足的时候
{
if(result>The_Number_to_guess)//所猜结果大了一点
{
ui->textBrowser->append("数字大了点");
result.clear();
}
else if(resulttextBrowser->append("数字小了点");
result.clear();
}
else//猜中结果
{
ui->textBrowser->append("恭喜你猜对了");
this->killTimer(Curtime);//计时器停止
QMessageBox::about(this,"成功","恭喜你猜对了!!");
ui->textBrowser->clear();
result.clear();
The_Number_to_guess.clear();
ui->start->blockSignals(false);
//插入播放胜利动画的页面
win_widget.show();
//跳转页面
ui->stackedWidget->setCurrentIndex(0);
}
}
}
}
//回退按钮
void GuessNum::on_back_clicked()
{
if(result.size()==1)
{
result.clear();
ui->textBrowser->clear();
}
else if(result.size()==0)
{
ui->textBrowser->setText("请输入数字噢!!");
}
else
{
result.chop(1);//截断最后一位字符
//result[result.size()-1]='\0';这样也可以
ui->textBrowser->setText(result);
}
}
我这两个窗口是使用子父窗口来实现的,因为我不知道怎么在stackedWidget中添加新的页面……但是还是有需要注意的地方,一开始我使用QPainter和QPixmap来实现整个窗口的背景图,发现实现不了,然后使用了一个和窗口一样大的标签来贴QMovie,从而实现了这个需求。而对于定时关闭窗口这个需求,我一开始没想到close函数,后来使用计时器和close函数来实现定时关闭窗口。最后记得关闭计时器噢!!
胜利窗口头文件代码:
#ifndef YOUWIN_H
#define YOUWIN_H
#include
#include
#include
class youWin : public QWidget
{
Q_OBJECT
public:
explicit youWin(QWidget *parent = nullptr);
void timerEvent(QTimerEvent*);
signals:
private:
int timeId;
};
#endif // YOUWIN_H
胜利窗口实现代码:
#include "youwin.h"
#include
#include
#include
youWin::youWin(QWidget *parent) : QWidget(parent)
{
this->resize(800,550);
this->setWindowTitle("你赢了噢!!!");
timeId=0;
timeId=this->startTimer(5000);
QLabel*p=new QLabel(this);
p->resize(this->width(),this->height());
p->show();
QMovie*mov=new QMovie(":/new/prefix1/C:/Users/13764/Desktop/PARTS/QT/victory.gif");
p->setMovie(mov);
mov->start();
p->setScaledContents(true);
}
void youWin::timerEvent(QTimerEvent *)
{
this->killTimer(timeId);
this->close();
}
失败窗口头文件代码:
#ifndef YOULOSS_H
#define YOULOSS_H
#include
class youLoss : public QWidget
{
Q_OBJECT
public:
explicit youLoss(QWidget *parent = nullptr);
void timerEvent(QTimerEvent*);
signals:
private:
int timeId;
};
#endif // YOULOSS_H
失败窗口实现文件代码:
#include "youloss.h"
#include
#include
#include
youLoss::youLoss(QWidget *parent) : QWidget(parent)
{
this->resize(800,550);
this->setWindowTitle("你输了噢!!!");
timeId=0;
timeId=this->startTimer(5000);
QLabel*p=new QLabel(this);
p->resize(this->width(),this->height());
p->show();
QMovie*mov=new QMovie(":/new/prefix1/C:/Users/13764/Desktop/PARTS/QT/default.gif");
p->setMovie(mov);
mov->start();
p->setScaledContents(true);
}
void youLoss::timerEvent(QTimerEvent *)
{
this->killTimer(timeId);
this->close();
}
运行:
主窗口的主界面
主窗口的游戏界面
当游戏胜利时
当游戏失败时