Qt项目-翻金币游戏

Posted 北極星

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Qt项目-翻金币游戏相关的知识,希望对你有一定的参考价值。

 

-项目概述-

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

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

 

-项目预览-

 

-程序框架- 

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

 

-代码资源下载-

 运行平台:

 

主界面代码:

 #include "mainwindow.h"
 #include "ui_mainwindow.h"
 #include <QPainter>
 #include <QMenuBar>
 #include <QDebug>
 #include <QSound>
 #include <QTimer>
 #include "mybutton.h"
 
 
 MainWindow::MainWindow(QWidget *parent) :
     QMainWindow(parent),
     ui(new Ui::MainWindow)
 
     ui->setupUi(this);
 
 
 //-------------------------------------------------------------主窗口设置-------------------------------------------------------------------//
     // 1.主窗口场景设置
     this->setFixedSize(360, 360*1.7);
     this->setWindowIcon(QPixmap(":/res/Coin0001.png"));
     this->setWindowTitle("翻金币");
 
     // 2.主窗口控件设置
     connect(ui->actionExit, &QAction::triggered, [=]()
         this->close();
     );
 
     // 3.创建关卡选择界面指针对象,同时监听关卡按钮前线发回的信号
     this->CustomWidget = new ChooseCustoms;
 
     connect(CustomWidget, &ChooseCustoms::ChooseCustomBacksig, [=]()
         this->setGeometry(CustomWidget->geometry());
         CustomWidget->hide();
         this->show();
     );
 
     // 4.创建并移动开始按钮对象
     MyButton *startBtn = new MyButton(":/res/MenuSceneStartButton.png");
     startBtn->setParent(this);
     startBtn->move((this->width() - startBtn->width())*0.5, this->height()*0.7);
 
     // 5.播放开始按钮点击音效
     QSound *startSound = new QSound(":/res/TapButtonSound.wav", this);
     
     connect(startBtn, &MyButton::clicked, [=]()
         qDebug() << "点击了开始按钮";        
         startBtn->jumpDown();       
         startSound->play();
         startBtn->jumpUp();
 
         QTimer::singleShot(400, this, [=]() this->hide(); CustomWidget->show(); );
     );
 
 
 
 
 
 //-------------------------------------------------------------主窗口绘图事件绘制界面-------------------------------------------------------------------//
 void MainWindow::paintEvent(QPaintEvent *)
 
     QPainter painter(this);
 
     // 绘制主场景背景界面
     QPixmap pix;
     pix.load(":/res/海滩.jpg");
     painter.drawPixmap(QRect(0, 0, this->width(), this->height()), pix);
 
     // 绘制主场景图标
     pix.load(":/res/Title.png");
     pix = pix.scaled(pix.width()*0.7, pix.height()*0.7);
     painter.drawPixmap(10, 30, pix.width(), pix.height() , pix);
 
 
 
 MainWindow::~MainWindow()
 
     delete ui;
 

 

 

 

 

关卡选择界面函数:

 #include "choosecustoms.h"
 #include <QMenuBar>
 #include <QPainter>
 #include <QSound>
 #include <QLabel>
 #include <QTimer>
 #include <QDebug>
 
 ChooseCustoms::ChooseCustoms(QWidget *parent) : QMainWindow(parent)
 
 //-------------------------------------------------------------主窗口设置-------------------------------------------------------------------//
     // 1.场景以及图标,标题设置
     this->setFixedSize(360, 360*1.7);
     this->setWindowIcon(QPixmap(":/res/Coin0001.png"));
     this->setWindowTitle("翻金币");
 
     // 2.创建菜单栏,创建关闭按钮
     QMenuBar *bar = this->menuBar();
     this->setMenuBar(bar);
     QMenu *startMenu = bar->addMenu("开始");
     QAction *quitAction = startMenu->addAction("退出");
 
     connect(quitAction, &QAction::triggered, [=]()
         this->hide();
     );
 
     // 3.返回按钮,返回按钮点击后返回的信号
     MyButton *retBtn = new MyButton(":/res/BackButton.png", ":/res/BackButtonSelected.png");
     retBtn->setParent(this);
     retBtn->move(this->width()-retBtn->width(), this->height()-retBtn->height());
 
 
     connect(retBtn, &MyButton::clicked, [=]()
         qDebug() << "点击了返回按钮";
         QSound *retSound = new QSound(":/res/BackButtonSound.wav", this);
         retSound->play();
         QTimer::singleShot(400, this, [=]() emit this->ChooseCustomBacksig(); );
     );
 
 //-------------------------------------------------------------for循环创建关卡选择按钮----------------------------------------------------------//
     // 4.创建关卡选择按钮
     for(int i = 0; i < 20; i++)
     
         // 绘制按钮图标
         MyButton *customBtn = new MyButton(":/res/LevelIcon.png");
         customBtn->setParent(this);
         customBtn->move(45 + (i%4)*70 , 150 + (i/4)*70);  // 我们要一个4x5的矩阵
         customBtnArray[i] = customBtn;
 
         // 关联每一个按钮的启动函数
         connect(customBtn, &MyButton::clicked, [=]()
 
             // 关卡选择按钮上锁,其余的按钮不能点击
             for(int i = 0; i < 20; i++)
             
                 customBtnArray[i]->isclick = true;
             
             qDebug() << "选择了" << i+1 << "关卡";
             if(this->coinfligwidget == NULL)
                           
                 customBtn->jumpDown();
                 customBtn->jumpUp();
                 QSound *chooseSound = new QSound(":/res/TapButtonSound.wav", this);
                 chooseSound->play();
 
                 QTimer::singleShot(400, this, [=]()
                     this->hide();
                     this->coinfligwidget = new CoinFligWidget(i+1);
                     coinfligwidget->setGeometry(this->geometry());
                     coinfligwidget->show();
 
                     // 关卡选择按钮解锁,其余的按钮可以点击
                     for(int i = 0; i < 20; i++)
                     
                         customBtnArray[i]->isclick = false;
                     
 
                     connect(coinfligwidget, &CoinFligWidget::CoinFligBacksig, [=]()
                         this->setGeometry(coinfligwidget->geometry());
                         this->show();
                         delete coinfligwidget;
                         coinfligwidget = NULL;
                     );
                 );
                        
         );
 
         // 绘制按钮数字
         QLabel *label = new QLabel;
         label->setParent(this);
         label->setFixedSize(customBtn->width(), customBtn->height());
         label->setText(QString::number(i+1));
         label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
         label->move(45 + (i%4)*70 , 150 + (i/4)*70);
         label->setAttribute(Qt::WA_TransparentForMouseEvents,true);  // 鼠标事件穿透
     
 
 
 //-------------------------------------------------------------主窗口绘图事件绘制界面--------------------------------------------------------------//
 
 void ChooseCustoms::paintEvent(QPaintEvent *event)
 
     QPainter painter(this);
     QPixmap pix;
     pix.load(":/res/海滩1.jpg");
     painter.drawPixmap(0, 0, this->width(), this->height(), pix);
 
     pix.load(":/res/Title.png");
     painter.drawPixmap((this->width() - pix.width())*0.5, 30, pix.width(), pix.height(), pix);
 

 

翻金币页面代码:

 #include "coinfligwidget.h"
 #include "dataconfig.h"
 #include "mybutton.h"
 #include <QPropertyAnimation>
 #include <QMenuBar>
 #include <iostream>
 #include <QPainter>
 #include <QDebug>
 #include <QSound>
 #include <QTimer>
 
 
 
 CoinFligWidget::CoinFligWidget(int index)
 
 //-------------------------------------------------------------初始化数据-------------------------------------------------------------------//
     this->levalIndex = index;
     dataConfig config;
     for(int i = 0; i < 4; i++)
     
         for(int j = 0; j < 4; j++)
         
             gameArray[i][j] = config.mData[this->levalIndex][i][j];
         
     
 //-------------------------------------------------------------主窗口设置-------------------------------------------------------------------//
     // 1.场景以及图标,标题设置
     this->setFixedSize(360, 360*1.7);
 
     this->setWindowIcon(QPixmap(":/res/Coin0001.png"));
     this->setWindowTitle("翻金币");
 
     // 2.创建菜单栏,创建关闭按钮
     QMenuBar *bar = this->menuBar();
     this->setMenuBar(bar);
     QMenu *startMenu = bar->addMenu("开始");
     QAction *quickAction = startMenu->addAction("退出");
 
     connect(quickAction, &QAction::triggered, [=]()
         this->hide();
     );
 
     // 3.返回按钮,返回按钮发出的信号
     MyButton *retBtn = new MyButton(":/res/BackButton.png", ":/res/BackButtonSelected.png");
     retBtn->setParent(this);
     retBtn->move(this->width()-retBtn->width(), this->height()-retBtn->height());
 
     connect(retBtn, &MyButton::clicked, [=]()
         qDebug() << "点击了返回按钮";
         QSound *chooseSound = new QSound(":/res/TapButtonSound.wav", this);
         chooseSound->play();
         QTimer::singleShot(400, this, [=]()  emit this->CoinFligBacksig(); );
     );
 
     // 4.显示当前关卡
     QLabel *label = new QLabel(this);
     QFont font;
     font.setFamily("华文新魏");
     font.setPointSize(20);
     label->setFont(font);
     QString str = QString("Leavel: %1").arg(this->levalIndex);
     label->setText(str);
     label->setGeometry(QRect(20, this->height()-75, 120, 50));
 
     // 5.将胜利图片创建好,如果胜利触发了,将图片弹下去即可
     QLabel *winLabel = new QLabel(this);
     QPixmap temPix;
     temPix.load(":/res/LevelCompletedDialogBg.png");
     winLabel->setGeometry(0, 0, temPix.width(), temPix.height());
     winLabel->setPixmap(temPix);
     winLabel->move((this->width() - temPix.width())*0.5, -temPix.height());
 
     // 翻金币音效
     QSound *flipSound = new QSound(":/res/ConFlipSound.wav",this);
 
 
 //-------------------------------------------------------------金币初始化-------------------------------------------------------------------//
     for(int i = 0; i < 4; i++)
     
         for(int j = 0; j < 4; j++)
         
             // 5.创建金币背景图片
             QLabel *label = new QLabel(this);
             label->setGeometry(0, 0, 50, 50);
             label->setPixmap(QPixmap(":/res/BoardNode.png"));
             label->move(80 + i*50, 200 + j*50);
 
             // 6.初始化金币
             QString img;
             if(gameArray[i][j] == 1)
             
                 img = ":/res/Coin0001.png";
             
             else
             
                 img = ":/res/Coin0008.png";
             
 
             MyCoin *coin = new MyCoin(img);
             coin->setParent(this);
             coin->move(82 + i*50,203 + j*50);
 
             // 为每个金币属性赋值,1.记录坐标 2.记录正反
             coin->posX = i;
             coin->posY = j;
             coin->flag = gameArray[i][j];
             coinBtn[i][j] = coin;           
 
             // 7.监听每个按钮的点击
             connect(coin, &MyCoin::clicked, [=]()
                 flipSound->play();
 
                 // 在此颗金币点击的瞬间,其余金币全部禁用,鼠标拦截事件弹出
                 for(int i = 0; i < 4; i++)
                 
                     for(int j = 0; j < 4; j++)
                     
                         this->coinBtn[i][j]->isWin = true;
                     
                 
 
                 // 翻转金币
                 coin->changflag();
                 this->gameArray[i][j] = this->gameArray[i][j] == 0 ? 1 : 0;
 
 //-------------------------------------------------------------周围金币翻转,并且判断输赢-------------------------------------------------------//
                 QTimer::singleShot(300, this, [=]()
                     this->aroundChang(i, j, coin);
                     this->judgeWin(winLabel);
                 );
             );
         
     
 
 
 // ->将周围金币进行翻转
 void CoinFligWidget::aroundChang(int i, int j, MyCoin *coin)
 
     if(coin->posX+1 <= 3)
     
         coinBtn[coin->posX+1][coin->posY]->changflag();
         gameArray[coin->posX+1][coin->posY] = gameArray[i][j] == 0 ? 1 : 0;
     
     if(coin->posX-1 >= 0)
     
         coinBtn[coin->posX-1][coin->posY]->changflag();
         gameArray[coin->posX-1][coin->posY] = gameArray[i][j] == 0 ? 1 : 0;
     
     if(coin->posY+1 <= 3)
     
         coinBtn[coin->posX][coin->posY+1]->changflag();
         gameArray[coin->posX][coin->posY+1] = gameArray[i][j] == 0 ? 1 : 0;
     
     if(coin->posY-1 >= 0)
     
         coinBtn[coin->posX][coin->posY-1]->changflag();
         gameArray[coin->posX][coin->posY-1] = gameArray[i][j] == 0 ? 1 : 0;
     
 
     for(int i = 0; i < 4; i++)
     
         for(int j = 0; j < 4; j++)
         
             this->coinBtn[i][j]->isWin = false;
         
     
 
 
 // ->判断是否胜利
 void CoinFligWidget::judgeWin(QLabel *label)
 
     this->isWin = true;
     for(int i = 0; i < 4; i++)
     
         for(int j = 0; j < 4; j++)
                  
             if(this->coinBtn[i][j]->flag == false)
             
                 this->isWin = false;
                 break;
                       
         
     
 
     if(this->isWin)
     
         qDebug() << "亲爱的,你的的确确是赢了!";
         // 胜利按钮音效
         QSound *winSound = new QSound(":/res/LevelWinSound.wav",this);
         winSound->play();
         QPropertyAnimation *animation = new QPropertyAnimation(label, "geometry");
         animation->setDuration(1000);
         animation->setStartValue(QRect(label->x(), label->y(), label->width(), label->height()));
         animation->setEndValue(QRect(label->x(), label->y()+144, label->width(), label->height()));
         animation->setEasingCurve(QEasingCurve::OutBounce);
         animation->start();
 
         // 赢了之后禁止翻转按钮
         for(int i = 0; i < 4; i++)
         
             for(int j = 0; j < 4; j++)
             
                 this->coinBtn[i][j]->isWin = true;
             
         
        
 
 
 //-------------------------------------------------------------主窗口绘图事件绘制界面--------------------------------------------------------------//
 void CoinFligWidget::paintEvent(QPaintEvent *event)
 
     QPainter painter(this);
     QPixmap pix;
 
     // 加载背景
     pix.load(":/res/海滩.jpg");
     painter.drawPixmap(QRect(0, 0, this->width(), this->height()), pix);
 
     // 加载标题
     pix.load(":/res/Title.png");
     pix = pix.scaled(pix.width()*0.5, pix.height()*0.5);
     painter.drawPixmap(10,30,pix.width(),pix.height(),pix);
 

 

-总结-

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

 

以上是关于Qt项目-翻金币游戏的主要内容,如果未能解决你的问题,请参考以下文章

新星计划python赛道pygame让你一步步实现翻牌游戏(金币旋转大头贴等),打造更有趣的新星之旅

新星计划python赛道pygame让你一步步实现翻牌游戏(金币旋转大头贴等),打造更有趣的新星之旅

1-4金币阵列问题

纯JavaScript入门级小游戏:兔子抢金币(附演示地址+源码)

关于新项目——活动

特工17Agent17汉化版游戏破解金币方法修改破解金币的增加方法