Qt项目-翻金币游戏

 

-项目概述-

Qt基础课程完结项目,完成一款小游戏并封装:翻金币游戏,通过点击金币进行翻面,让所有金币为同一面就游戏通过进入下一关。

过程中会使用前面学到的 “信号和槽”,“Qt图片资源显示”,“Qt播放音频”,“Qt绘图函数”,“Qt消息控件”等等知识。是一次前面所学知识的汇总。

 

-项目预览-

 

-程序框架- 

框架如下,(因为这个项目完成有些时间了,现在才记录下来,流程部分是看的当时的程序注释,有些不明白的地方可以私信我)

 

-代码资源下载-

 运行平台:

 

主界面代码:

 1 #include "mainwindow.h"
 2 #include "ui_mainwindow.h"
 3 #include <QPainter>
 4 #include <QMenuBar>
 5 #include <QDebug>
 6 #include <QSound>
 7 #include <QTimer>
 8 #include "mybutton.h"
 9 
10 
11 MainWindow::MainWindow(QWidget *parent) :
12     QMainWindow(parent),
13     ui(new Ui::MainWindow)
14 {
15     ui->setupUi(this);
16 
17 
18 //-------------------------------------------------------------主窗口设置-------------------------------------------------------------------//
19     // 1.主窗口场景设置
20     this->setFixedSize(360, 360*1.7);
21     this->setWindowIcon(QPixmap(":/res/Coin0001.png"));
22     this->setWindowTitle("翻金币");
23 
24     // 2.主窗口控件设置
25     connect(ui->actionExit, &QAction::triggered, [=](){
26         this->close();
27     });
28 
29     // 3.创建关卡选择界面指针对象,同时监听关卡按钮前线发回的信号
30     this->CustomWidget = new ChooseCustoms;
31 
32     connect(CustomWidget, &ChooseCustoms::ChooseCustomBacksig, [=](){
33         this->setGeometry(CustomWidget->geometry());
34         CustomWidget->hide();
35         this->show();
36     });
37 
38     // 4.创建并移动开始按钮对象
39     MyButton *startBtn = new MyButton(":/res/MenuSceneStartButton.png");
40     startBtn->setParent(this);
41     startBtn->move((this->width() - startBtn->width())*0.5, this->height()*0.7);
42 
43     // 5.播放开始按钮点击音效
44     QSound *startSound = new QSound(":/res/TapButtonSound.wav", this);
45     
46     connect(startBtn, &MyButton::clicked, [=](){
47         qDebug() << "点击了开始按钮";        
48         startBtn->jumpDown();       
49         startSound->play();
50         startBtn->jumpUp();
51 
52         QTimer::singleShot(400, this, [=](){ this->hide(); CustomWidget->show(); });
53     });
54 }
55 
56 
57 
58 
59 //-------------------------------------------------------------主窗口绘图事件绘制界面-------------------------------------------------------------------//
60 void MainWindow::paintEvent(QPaintEvent *)
61 {
62     QPainter painter(this);
63 
64     // 绘制主场景背景界面
65     QPixmap pix;
66     pix.load(":/res/海滩.jpg");
67     painter.drawPixmap(QRect(0, 0, this->width(), this->height()), pix);
68 
69     // 绘制主场景图标
70     pix.load(":/res/Title.png");
71     pix = pix.scaled(pix.width()*0.7, pix.height()*0.7);
72     painter.drawPixmap(10, 30, pix.width(), pix.height() , pix);
73 }
74 
75 
76 MainWindow::~MainWindow()
77 {
78     delete ui;
79 }

 

 

 

 

关卡选择界面函数:

  1 #include "choosecustoms.h"
  2 #include <QMenuBar>
  3 #include <QPainter>
  4 #include <QSound>
  5 #include <QLabel>
  6 #include <QTimer>
  7 #include <QDebug>
  8 
  9 ChooseCustoms::ChooseCustoms(QWidget *parent) : QMainWindow(parent)
 10 {
 11 //-------------------------------------------------------------主窗口设置-------------------------------------------------------------------//
 12     // 1.场景以及图标,标题设置
 13     this->setFixedSize(360, 360*1.7);
 14     this->setWindowIcon(QPixmap(":/res/Coin0001.png"));
 15     this->setWindowTitle("翻金币");
 16 
 17     // 2.创建菜单栏,创建关闭按钮
 18     QMenuBar *bar = this->menuBar();
 19     this->setMenuBar(bar);
 20     QMenu *startMenu = bar->addMenu("开始");
 21     QAction *quitAction = startMenu->addAction("退出");
 22 
 23     connect(quitAction, &QAction::triggered, [=](){
 24         this->hide();
 25     });
 26 
 27     // 3.返回按钮,返回按钮点击后返回的信号
 28     MyButton *retBtn = new MyButton(":/res/BackButton.png", ":/res/BackButtonSelected.png");
 29     retBtn->setParent(this);
 30     retBtn->move(this->width()-retBtn->width(), this->height()-retBtn->height());
 31 
 32 
 33     connect(retBtn, &MyButton::clicked, [=](){
 34         qDebug() << "点击了返回按钮";
 35         QSound *retSound = new QSound(":/res/BackButtonSound.wav", this);
 36         retSound->play();
 37         QTimer::singleShot(400, this, [=](){ emit this->ChooseCustomBacksig(); });
 38     });
 39 
 40 //-------------------------------------------------------------for循环创建关卡选择按钮----------------------------------------------------------//
 41     // 4.创建关卡选择按钮
 42     for(int i = 0; i < 20; i++)
 43     {
 44         // 绘制按钮图标
 45         MyButton *customBtn = new MyButton(":/res/LevelIcon.png");
 46         customBtn->setParent(this);
 47         customBtn->move(45 + (i%4)*70 , 150 + (i/4)*70);  // 我们要一个4x5的矩阵
 48         customBtnArray[i] = customBtn;
 49 
 50         // 关联每一个按钮的启动函数
 51         connect(customBtn, &MyButton::clicked, [=](){
 52 
 53             // 关卡选择按钮上锁,其余的按钮不能点击
 54             for(int i = 0; i < 20; i++)
 55             {
 56                 customBtnArray[i]->isclick = true;
 57             }
 58             qDebug() << "选择了" << i+1 << "关卡";
 59             if(this->coinfligwidget == NULL)
 60             {              
 61                 customBtn->jumpDown();
 62                 customBtn->jumpUp();
 63                 QSound *chooseSound = new QSound(":/res/TapButtonSound.wav", this);
 64                 chooseSound->play();
 65 
 66                 QTimer::singleShot(400, this, [=](){
 67                     this->hide();
 68                     this->coinfligwidget = new CoinFligWidget(i+1);
 69                     coinfligwidget->setGeometry(this->geometry());
 70                     coinfligwidget->show();
 71 
 72                     // 关卡选择按钮解锁,其余的按钮可以点击
 73                     for(int i = 0; i < 20; i++)
 74                     {
 75                         customBtnArray[i]->isclick = false;
 76                     }
 77 
 78                     connect(coinfligwidget, &CoinFligWidget::CoinFligBacksig, [=](){
 79                         this->setGeometry(coinfligwidget->geometry());
 80                         this->show();
 81                         delete coinfligwidget;
 82                         coinfligwidget = NULL;
 83                     });
 84                 });
 85             }           
 86         });
 87 
 88         // 绘制按钮数字
 89         QLabel *label = new QLabel;
 90         label->setParent(this);
 91         label->setFixedSize(customBtn->width(), customBtn->height());
 92         label->setText(QString::number(i+1));
 93         label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
 94         label->move(45 + (i%4)*70 , 150 + (i/4)*70);
 95         label->setAttribute(Qt::WA_TransparentForMouseEvents,true);  // 鼠标事件穿透
 96     }
 97 }
 98 
 99 //-------------------------------------------------------------主窗口绘图事件绘制界面--------------------------------------------------------------//
100 
101 void ChooseCustoms::paintEvent(QPaintEvent *event)
102 {
103     QPainter painter(this);
104     QPixmap pix;
105     pix.load(":/res/海滩1.jpg");
106     painter.drawPixmap(0, 0, this->width(), this->height(), pix);
107 
108     pix.load(":/res/Title.png");
109     painter.drawPixmap((this->width() - pix.width())*0.5, 30, pix.width(), pix.height(), pix);
110 }

 

翻金币页面代码:

  1 #include "coinfligwidget.h"
  2 #include "dataconfig.h"
  3 #include "mybutton.h"
  4 #include <QPropertyAnimation>
  5 #include <QMenuBar>
  6 #include <iostream>
  7 #include <QPainter>
  8 #include <QDebug>
  9 #include <QSound>
 10 #include <QTimer>
 11 
 12 
 13 
 14 CoinFligWidget::CoinFligWidget(int index)
 15 {
 16 //-------------------------------------------------------------初始化数据-------------------------------------------------------------------//
 17     this->levalIndex = index;
 18     dataConfig config;
 19     for(int i = 0; i < 4; i++)
 20     {
 21         for(int j = 0; j < 4; j++)
 22         {
 23             gameArray[i][j] = config.mData[this->levalIndex][i][j];
 24         }
 25     }
 26 //-------------------------------------------------------------主窗口设置-------------------------------------------------------------------//
 27     // 1.场景以及图标,标题设置
 28     this->setFixedSize(360, 360*1.7);
 29 
 30     this->setWindowIcon(QPixmap(":/res/Coin0001.png"));
 31     this->setWindowTitle("翻金币");
 32 
 33     // 2.创建菜单栏,创建关闭按钮
 34     QMenuBar *bar = this->menuBar();
 35     this->setMenuBar(bar);
 36     QMenu *startMenu = bar->addMenu("开始");
 37     QAction *quickAction = startMenu->addAction("退出");
 38 
 39     connect(quickAction, &QAction::triggered, [=](){
 40         this->hide();
 41     });
 42 
 43     // 3.返回按钮,返回按钮发出的信号
 44     MyButton *retBtn = new MyButton(":/res/BackButton.png", ":/res/BackButtonSelected.png");
 45     retBtn->setParent(this);
 46     retBtn->move(this->width()-retBtn->width(), this->height()-retBtn->height());
 47 
 48     connect(retBtn, &MyButton::clicked, [=](){
 49         qDebug() << "点击了返回按钮";
 50         QSound *chooseSound = new QSound(":/res/TapButtonSound.wav", this);
 51         chooseSound->play();
 52         QTimer::singleShot(400, this, [=](){  emit this->CoinFligBacksig(); });
 53     });
 54 
 55     // 4.显示当前关卡
 56     QLabel *label = new QLabel(this);
 57     QFont font;
 58     font.setFamily("华文新魏");
 59     font.setPointSize(20);
 60     label->setFont(font);
 61     QString str = QString("Leavel: %1").arg(this->levalIndex);
 62     label->setText(str);
 63     label->setGeometry(QRect(20, this->height()-75, 120, 50));
 64 
 65     // 5.将胜利图片创建好,如果胜利触发了,将图片弹下去即可
 66     QLabel *winLabel = new QLabel(this);
 67     QPixmap temPix;
 68     temPix.load(":/res/LevelCompletedDialogBg.png");
 69     winLabel->setGeometry(0, 0, temPix.width(), temPix.height());
 70     winLabel->setPixmap(temPix);
 71     winLabel->move((this->width() - temPix.width())*0.5, -temPix.height());
 72 
 73     // 翻金币音效
 74     QSound *flipSound = new QSound(":/res/ConFlipSound.wav",this);
 75 
 76 
 77 //-------------------------------------------------------------金币初始化-------------------------------------------------------------------//
 78     for(int i = 0; i < 4; i++)
 79     {
 80         for(int j = 0; j < 4; j++)
 81         {
 82             // 5.创建金币背景图片
 83             QLabel *label = new QLabel(this);
 84             label->setGeometry(0, 0, 50, 50);
 85             label->setPixmap(QPixmap(":/res/BoardNode.png"));
 86             label->move(80 + i*50, 200 + j*50);
 87 
 88             // 6.初始化金币
 89             QString img;
 90             if(gameArray[i][j] == 1)
 91             {
 92                 img = ":/res/Coin0001.png";
 93             }
 94             else
 95             {
 96                 img = ":/res/Coin0008.png";
 97             }
 98 
 99             MyCoin *coin = new MyCoin(img);
100             coin->setParent(this);
101             coin->move(82 + i*50,203 + j*50);
102 
103             // 为每个金币属性赋值,1.记录坐标 2.记录正反
104             coin->posX = i;
105             coin->posY = j;
106             coin->flag = gameArray[i][j];
107             coinBtn[i][j] = coin;           
108 
109             // 7.监听每个按钮的点击
110             connect(coin, &MyCoin::clicked, [=](){
111                 flipSound->play();
112 
113                 // 在此颗金币点击的瞬间,其余金币全部禁用,鼠标拦截事件弹出
114                 for(int i = 0; i < 4; i++)
115                 {
116                     for(int j = 0; j < 4; j++)
117                     {
118                         this->coinBtn[i][j]->isWin = true;
119                     }
120                 }
121 
122                 // 翻转金币
123                 coin->changflag();
124                 this->gameArray[i][j] = this->gameArray[i][j] == 0 ? 1 : 0;
125 
126 //-------------------------------------------------------------周围金币翻转,并且判断输赢-------------------------------------------------------//
127                 QTimer::singleShot(300, this, [=](){
128                     this->aroundChang(i, j, coin);
129                     this->judgeWin(winLabel);
130                 });
131             });
132         }
133     }
134 }
135 
136 // ->将周围金币进行翻转
137 void CoinFligWidget::aroundChang(int i, int j, MyCoin *coin)
138 {
139     if(coin->posX+1 <= 3)
140     {
141         coinBtn[coin->posX+1][coin->posY]->changflag();
142         gameArray[coin->posX+1][coin->posY] = gameArray[i][j] == 0 ? 1 : 0;
143     }
144     if(coin->posX-1 >= 0)
145     {
146         coinBtn[coin->posX-1][coin->posY]->changflag();
147         gameArray[coin->posX-1][coin->posY] = gameArray[i][j] == 0 ? 1 : 0;
148     }
149     if(coin->posY+1 <= 3)
150     {
151         coinBtn[coin->posX][coin->posY+1]->changflag();
152         gameArray[coin->posX][coin->posY+1] = gameArray[i][j] == 0 ? 1 : 0;
153     }
154     if(coin->posY-1 >= 0)
155     {
156         coinBtn[coin->posX][coin->posY-1]->changflag();
157         gameArray[coin->posX][coin->posY-1] = gameArray[i][j] == 0 ? 1 : 0;
158     }
159 
160     for(int i = 0; i < 4; i++)
161     {
162         for(int j = 0; j < 4; j++)
163         {
164             this->coinBtn[i][j]->isWin = false;
165         }
166     }
167 }
168 
169 // ->判断是否胜利
170 void CoinFligWidget::judgeWin(QLabel *label)
171 {
172     this->isWin = true;
173     for(int i = 0; i < 4; i++)
174     {
175         for(int j = 0; j < 4; j++)
176         {         
177             if(this->coinBtn[i][j]->flag == false)
178             {
179                 this->isWin = false;
180                 break;
181             }          
182         }
183     }
184 
185     if(this->isWin)
186     {
187         qDebug() << "亲爱的,你的的确确是赢了!";
188         // 胜利按钮音效
189         QSound *winSound = new QSound(":/res/LevelWinSound.wav",this);
190         winSound->play();
191         QPropertyAnimation *animation = new QPropertyAnimation(label, "geometry");
192         animation->setDuration(1000);
193         animation->setStartValue(QRect(label->x(), label->y(), label->width(), label->height()));
194         animation->setEndValue(QRect(label->x(), label->y()+144, label->width(), label->height()));
195         animation->setEasingCurve(QEasingCurve::OutBounce);
196         animation->start();
197 
198         // 赢了之后禁止翻转按钮
199         for(int i = 0; i < 4; i++)
200         {
201             for(int j = 0; j < 4; j++)
202             {
203                 this->coinBtn[i][j]->isWin = true;
204             }
205         }
206     }   
207 }
208 
209 //-------------------------------------------------------------主窗口绘图事件绘制界面--------------------------------------------------------------//
210 void CoinFligWidget::paintEvent(QPaintEvent *event)
211 {
212     QPainter painter(this);
213     QPixmap pix;
214 
215     // 加载背景
216     pix.load(":/res/海滩.jpg");
217     painter.drawPixmap(QRect(0, 0, this->width(), this->height()), pix);
218 
219     // 加载标题
220     pix.load(":/res/Title.png");
221     pix = pix.scaled(pix.width()*0.5, pix.height()*0.5);
222     painter.drawPixmap(10,30,pix.width(),pix.height(),pix);
223 }

 

-总结-

  • 这一次项目让我有了对C++的重新审视,刚学的时候:哟,这不就是C嘛,中途:WOC,这是什么??? 做完项目:原来这就是C++啊<仍然懵。。。>
  • 要想开启一个项目,一定是先主体后局部,先框架后函数,以前我写代码总是热衷于函数某一个功能的优化,导致项目迟迟难以推进,这次真正见识到了,先搭框架后细化的感觉有多爽。
  • Qt的环境变量花了我大量时间配置......

 

posted @ 2023-01-18 21:25  北極星  阅读(322)  评论(0编辑  收藏  举报