[Qt 5.6.2] 利用Qt實現一個難度可變的2048小遊戲

利用Qt實現一個難度隨時可調的2048小遊戲

 

1、遊戲簡介

一、規則創新ios

  勝利條件:達成2048dom

  難度變化:玩家能夠經過調整難度條來控制隨機池(二、四、八、16)中各個數出現的機率,同時也會改變分數的加成比例ide

  移動觸發:每次移動後會從隨機池中按照機率隨機選取一個數,將其隨機放置在一個空餘位置上函數

  分數計算:總分=基礎分+加成分,基礎分+=合併的數值,加成分+=隨機生成的數值*加成比例ui

 

二、遊戲效果this

   

 

 

2、設計思路

  先將該項目分爲遊戲入口、主窗口設計與遊戲邏輯三個主要模塊,再在這三個模塊的基礎上繼續細分,分割成若干個小的功能模塊,最後逐一實現。由MainWindow與GameLogic兩個類分別實現主界面的顯示功能與遊戲的實現邏輯。spa

  程序入口較爲簡單,故不贅述。設計

  主窗口設計主要實現棋盤數據的顯示與顏色變化、分數與難度的顯示、檢測方向鍵並鏈接進入遊戲邏輯的入口。3d

  遊戲邏輯是整個項目的核心部分,主要實現整個遊戲的邏輯判斷,根據主窗口提供的難度計算出難度係數與隨機池各個數據出現機率。code

 

 

3、代碼分析

  文件具體分爲gamelogic.cpp、main.cpp與mainwindow.cpp三個.cpp文件,gamelogic.h、mainwindow.h兩個.h文件與一個mainwindow.ui文件。

一、程序入口:main.cpp

 1 #include "mainwindow.h"
 2 #include <QApplication>
 3 
 4 int main(int argc, char *argv[])
 5 {
 6     QApplication a(argc, argv);
 7     MainWindow w;
 8     w.show();
 9 
10     return a.exec();
11 }

 若是想進行人員管理與登錄的拓展可改成如下代碼,可自行設計login登陸規則:

 1 #include "mainwindow.h"
 2 #include <QApplication>
 3 
 4 int main(int argc, char *argv[])
 5 {
 6     QApplication a(argc, argv);
 7     MainWindow w;
 8     w.show();
 9 
10     return a.exec();
11 }
View Code

 

 

二、主窗口設計:mainwindow.cpp/.h/.ui

2.1 mainwindow.ui

      

 

2.2 mainwindow.h

 1 #ifndef MAINWINDOW_H
 2 #define MAINWINDOW_H
 3 
 4 #include <QMainWindow>
 5 #include <QKeyEvent>
 6 #include <QDebug>
 7 #include <QMessageBox>
 8 #include <QTextBrowser>
 9 #include "gamelogic.h"
10 
11 namespace Ui {
12 class MainWindow;
13 }
14 
15 class MainWindow : public QMainWindow
16 {
17     Q_OBJECT
18 
19 public:
20     GameLogic* game;
21     explicit MainWindow(QWidget *parent = 0);
22     ~MainWindow();
23     void initAll(); 
24     void showMessage();
25     void showBroad();
26     void keyPressEvent(QKeyEvent *event);
27     void changeColor(QLabel* label, int num);
28 
29 private slots:
30     void on_pushButton_start_clicked();
31 
32     void on_pushButton_close_clicked();
33 
34     void on_horizontalSlider_valueChanged(int value);
35 
36 private:
37     Ui::MainWindow *ui;
38 };
39 
40 #endif // MAINWINDOW_H

 

2.3 mainwindow.cpp(代碼共177行,摺疊)

  1 #include "mainwindow.h"
  2 #include "ui_mainwindow.h"
  3 #include "gamelogic.h"
  4 
  5 MainWindow::MainWindow(QWidget *parent) :
  6     QMainWindow(parent),
  7     ui(new Ui::MainWindow)
  8 {
  9     game = new GameLogic;
 10     ui->setupUi(this);
 11     showBroad();
 12 }
 13 
 14 MainWindow::~MainWindow()
 15 {
 16     delete ui;
 17 }
 18 
 19 void MainWindow::initAll()
 20 {
 21     game->initAll();
 22     on_horizontalSlider_valueChanged(ui->horizontalSlider->value());
 23 }
 24 
 25 
 26 void MainWindow::on_pushButton_start_clicked()
 27 {
 28     ui->pushButton_start->setText("從新開始");
 29     initAll();
 30 
 31     game->createNum();
 32     game->createNum();
 33     game->setGameStart(true);
 34 
 35     showBroad();
 36     showMessage();
 37 }
 38 
 39 void MainWindow::on_pushButton_close_clicked()
 40 {
 41     this->close();
 42 }
 43 
 44 void MainWindow::on_horizontalSlider_valueChanged(int value)
 45 {
 46     value = ui->horizontalSlider->value();
 47     ui->label_showGradeUpCoefficient->setText(QString::number(value*2)+"%");
 48     game->setGradeUpCoefficient((float)ui->horizontalSlider->value()/100);
 49 
 50     if     (20 > value) ui->label_showDifficult->setText("簡單");
 51     else if(40 > value) ui->label_showDifficult->setText("正常");
 52     else if(60 > value) ui->label_showDifficult->setText("困難");
 53     else if(80 > value) ui->label_showDifficult->setText("地獄");
 54     else                ui->label_showDifficult->setText("混沌");
 55 }
 56 
 57 void MainWindow::keyPressEvent(QKeyEvent *event)
 58 {
 59     if(!game->getGameStart()) return;
 60     switch(event->key())
 61     {
 62     case Qt::Key_Up:    game->process(CMD_UP);    break;
 63     case Qt::Key_Down:  game->process(CMD_DOWN);  break;
 64     case Qt::Key_Left:  game->process(CMD_LEFT);  break;
 65     case Qt::Key_Right: game->process(CMD_RIGHT); break;
 66     }
 67     showBroad();
 68     showMessage();
 69     switch(game->judge())
 70     {
 71     case STAT_PROCESS: break;
 72     case STAT_WIN:  QMessageBox::information(NULL,"2048","大吉大利,今晚吃雞!"); break;
 73     case STAT_LOSE: QMessageBox::information(NULL,"2048","再接再礪,永不放棄!"); break;
 74     }
 75 }
 76 
 77 void MainWindow::showMessage()
 78 {
 79     ui->label_showGrade->setText(QString::number(game->getGrade()));
 80     ui->label_showGradeBasic->setText(QString::number(game->getGradeBasic()));
 81     ui->label_showGradeUp->setText(QString::number(game->getGradeUp()));
 82     ui->label_showStep->setText(QString::number(game->getStep()));
 83 }
 84 
 85 void MainWindow::showBroad()
 86 {
 87     //第一行
 88     if(game->getData(0,0)) ui->label_00->setText(QString::number(game->getData(0,0)));
 89     else                   ui->label_00->setText(" ");
 90     if(game->getData(0,1)) ui->label_01->setText(QString::number(game->getData(0,1)));
 91     else                   ui->label_01->setText(" ");
 92     if(game->getData(0,2)) ui->label_02->setText(QString::number(game->getData(0,2)));
 93     else                   ui->label_02->setText(" ");
 94     if(game->getData(0,3)) ui->label_03->setText(QString::number(game->getData(0,3)));
 95     else                   ui->label_03->setText(" ");
 96     changeColor(ui->label_00, game->getData(0,0));
 97     changeColor(ui->label_01, game->getData(0,1));
 98     changeColor(ui->label_02, game->getData(0,2));
 99     changeColor(ui->label_03, game->getData(0,3));
100 
101     //第二行
102     if(game->getData(1,0)) ui->label_10->setText(QString::number(game->getData(1,0)));
103     else                   ui->label_10->setText(" ");
104     if(game->getData(1,1)) ui->label_11->setText(QString::number(game->getData(1,1)));
105     else                   ui->label_11->setText(" ");
106     if(game->getData(1,2)) ui->label_12->setText(QString::number(game->getData(1,2)));
107     else                   ui->label_12->setText(" ");
108     if(game->getData(1,3)) ui->label_13->setText(QString::number(game->getData(1,3)));
109     else                   ui->label_13->setText(" ");
110     changeColor(ui->label_10, game->getData(1,0));
111     changeColor(ui->label_11, game->getData(1,1));
112     changeColor(ui->label_12, game->getData(1,2));
113     changeColor(ui->label_13, game->getData(1,3));
114 
115     //第三行
116     if(game->getData(2,0)) ui->label_20->setText(QString::number(game->getData(2,0)));
117     else                   ui->label_20->setText(" ");
118     if(game->getData(2,1)) ui->label_21->setText(QString::number(game->getData(2,1)));
119     else                   ui->label_21->setText(" ");
120     if(game->getData(2,2)) ui->label_22->setText(QString::number(game->getData(2,2)));
121     else                   ui->label_22->setText(" ");
122     if(game->getData(2,3)) ui->label_23->setText(QString::number(game->getData(2,3)));
123     else                   ui->label_23->setText(" ");
124     changeColor(ui->label_20, game->getData(2,0));
125     changeColor(ui->label_21, game->getData(2,1));
126     changeColor(ui->label_22, game->getData(2,2));
127     changeColor(ui->label_23, game->getData(2,3));
128 
129     //第四行
130     if(game->getData(3,0)) ui->label_30->setText(QString::number(game->getData(3,0)));
131     else                   ui->label_30->setText(" ");
132     if(game->getData(3,1)) ui->label_31->setText(QString::number(game->getData(3,1)));
133     else                   ui->label_31->setText(" ");
134     if(game->getData(3,2)) ui->label_32->setText(QString::number(game->getData(3,2)));
135     else                   ui->label_32->setText(" ");
136     if(game->getData(3,3)) ui->label_33->setText(QString::number(game->getData(3,3)));
137     else                   ui->label_33->setText(" ");
138     changeColor(ui->label_30, game->getData(3,0));
139     changeColor(ui->label_31, game->getData(3,1));
140     changeColor(ui->label_32, game->getData(3,2));
141     changeColor(ui->label_33, game->getData(3,3));
142 }
143 
144 //改變方塊的StyleSheet
145 void MainWindow::changeColor(QLabel* label, int num)
146 {
147     label->setAlignment(Qt::AlignCenter);
148     switch (num)
149     {
150     case 2:    label->setStyleSheet("background-color: rgb(238,228,218);"
151                                     "font:bold 75 30pt ""微軟雅黑"""); break;
152     case 4:    label->setStyleSheet("background-color: rgb(237,224,200);"
153                                     "font:bold 75 30pt ""微軟雅黑"""); break;
154     case 8:    label->setStyleSheet("background-color: rgb(242,177,121);"
155                                     "font:bold 75 30pt ""微軟雅黑"""); break;
156     case 16:   label->setStyleSheet("background-color: rgb(245,150,100);"
157                                     "font:bold 75 30pt ""微軟雅黑"""); break;
158     case 32:   label->setStyleSheet("background-color: rgb(245,125,95);"
159                                     "font:bold 75 30pt ""微軟雅黑"""); break;
160     case 64:   label->setStyleSheet("background-color: rgb(245,95,60);"
161                                     "font:bold 75 30pt ""微軟雅黑"""); break;
162     case 128:  label->setStyleSheet("background-color: rgb(237,207,114);"
163                                     "font:bold 75 25pt ""微軟雅黑"""); break;
164     case 256:  label->setStyleSheet("background-color: rgb(237,204,97);"
165                                     "font:bold 75 25pt ""微軟雅黑"""); break;
166     case 512:  label->setStyleSheet("background-color: rgb(237,204,97);"
167                                     "font:bold 75 25pt ""微軟雅黑"""); break;
168     case 1024: label->setStyleSheet("background-color: rgb(237,204,97);"
169                                     "font:bold 75 20pt ""微軟雅黑"""); break;
170     case 2048: label->setStyleSheet("background-color: rgb(237,204,97);"
171                                     "font:bold 75 20pt ""微軟雅黑"""); break;
172     default:   label->setStyleSheet("background-color: rgb(238,228,218);"
173                                     "font:bold 75 40pt ""微軟雅黑"""); break;
174     }
175 }
View Code
    ① 初始化全部數據,鎖定檢測:
    void initAll();
    ② 經過按鈕開始或結束遊戲,而且可隨時調節遊戲難度:
    void on_pushButton_start_clicked();

    void on_pushButton_close_clicked();
    void on_horizontalSlider_valueChanged(int value);
    ③ 顯示界面與各種信息,根據各個方塊的數值來調整遊戲顯示畫面:
    void showMessage();

    void showBroad();
    void changeColor(QLabel* label, int num);
    ④ 檢測方向鍵,執行成員變量game的邏輯函數:
    void keyPressEvent(QKeyEvent *event);


三、遊戲邏輯:gamelogic.cpp/.h
3.1 gamelogic.h
 1 #ifndef GAMELOGIC_H
 2 #define GAMELOGIC_H
 3 
 4 #include <iostream>
 5 
 6 #define ROW 4
 7 #define COL 4
 8 
 9 enum CMD
10 {
11     CMD_UP,
12     CMD_DOWN,
13     CMD_LEFT,
14     CMD_RIGHT,
15 };
16 
17 enum STAT
18 {
19     STAT_WAIT,
20     STAT_PROCESS,
21     STAT_WIN,
22     STAT_LOSE,
23 };
24 
25 class GameLogic
26 {
27 public:
28     GameLogic();
29     bool createNum();
30     void process(int cmd);
31     int judge();
32     void initAll();
33     void calProb();
34 
35     void moveUp();
36     void moveDown();
37     void moveLeft();
38     void moveRight();
39 
40     bool getGameStart();
41     void setGameStart(bool);
42     void setGradeUpCoefficient(float);
43     int getData(int,int);
44     int getGrade();
45     int getGradeBasic();
46     int getGradeUp();
47     int getStep();
48 
49 private:
50     bool gameStart;
51     int data[4][4];
52     float grade;
53     int gradeBasic;
54     float gradeUp;
55     int step;
56     float gradeUpCoefficient;
57     int prob2;
58     int prob4;
59     int prob8;
60     int prob16;
61 };
62 
63 #endif // GAMELOGIC_H

 

3.2 gamelogic.cpp(代碼共299行,摺疊)

  1 #include "gamelogic.h"
  2 #include "ui_mainwindow.h"
  3 
  4 #include <random>
  5 #include <iostream>
  6 #include <vector>
  7 #include <qDebug>
  8 using namespace std;
  9 
 10 GameLogic::GameLogic()
 11 {
 12     initAll();
 13 }
 14 
 15 void GameLogic::initAll()
 16 {
 17     for(int i=0; i<ROW; i++)
 18     {
 19         for(int j=0; j<COL; j++)
 20         {
 21             data[i][j] = 0;
 22         }
 23     }
 24     gameStart = false;
 25     grade = 0;
 26     gradeBasic = 0;
 27     gradeUp = 0;
 28     step = 0;
 29     gradeUpCoefficient = 0;
 30 
 31     prob2 = 0;
 32     prob4 = 0;
 33     prob8 = 0;
 34     prob16 = 0;
 35 }
 36 
 37 void GameLogic::calProb()
 38 {
 39     qDebug() << "gradeUpCoefficient:" << gradeUpCoefficient ;
 40     if(0.6 > gradeUpCoefficient) // 0->0.6
 41     {
 42         prob2 = 80-gradeUpCoefficient*100*0.5; // 80%->50%
 43         prob4 = 100;                           // 20%->50%
 44         prob8 = 0, prob16 = 0;                 // 0
 45         qDebug() << "2:" << prob2 << " 4:" << prob4 << " 8:" << prob8 << " 16:" << prob16 ;
 46     }
 47     else if(0.8 > gradeUpCoefficient) // 0.6->0.8
 48     {
 49         prob2 = 80-gradeUpCoefficient*100*0.5; // 50%->40%
 50         prob4 = 50+prob2;                      // 50%
 51         prob8 = 100;                           // 0->10%
 52         prob16 = 0;                            // 0
 53         qDebug() << "2:" << prob2 << " 4:" << prob4 << " 8:" << prob8 << " 16:" << prob16 ;
 54     }
 55     else if(1 >= gradeUpCoefficient)// 0.8->1.0
 56     {
 57         prob2 = 40;                                    // 40%
 58         prob4 = -10+gradeUpCoefficient*100*0.5+prob2;  // 30%->40%
 59         prob8 = -10+gradeUpCoefficient*100*0.25+prob4; // 10%->15%
 60         prob16 = 100;                                  // 0->5%
 61         qDebug() << "2:" << prob2 << " 4:" << prob4 << " 8:" << prob8 << " 16:" << prob16 ;
 62     }
 63 }
 64 
 65 bool GameLogic::createNum()
 66 {
 67     vector<int> indexSpace;
 68     for(int i=0; i<ROW; i++)
 69     {
 70         for(int j=0; j<COL; j++)
 71         {
 72             if(!data[i][j])
 73             {
 74                 indexSpace.push_back(i*4+j);
 75             }
 76         }
 77     }
 78     if(!indexSpace.empty())
 79     {
 80         int randNum = rand()%100;
 81         int randPlace = rand()%indexSpace.size();
 82         int chooseNum = -1;
 83 
 84         calProb();
 85         //qDebug() << "randNum:" << randNum;
 86         //qDebug() << "2:" << prob2 << " 4:" << prob4 << " 8:" << prob8 << " 16:" << prob16 ;
 87         if     (prob2 > randNum)  chooseNum = 2;
 88         else if(prob4 > randNum)  chooseNum = 4;
 89         else if(prob8 > randNum)  chooseNum = 8;
 90         else if(prob16 > randNum) chooseNum = 16;
 91         int x = indexSpace[randPlace]/4;
 92         int y = indexSpace[randPlace]%4;
 93         //qDebug("---------- %d %d----------",x,y);
 94         data[x][y] = chooseNum;
 95         gradeUp += 2*chooseNum*gradeUpCoefficient;
 96         grade = gradeBasic + gradeUp;
 97         return true;
 98     }
 99     else
100     {
101         return false;
102     }
103 }
104 
105 void GameLogic::process(int cmd)
106 {
107     switch(cmd)
108     {
109     case CMD_UP:    moveUp();    break;
110     case CMD_DOWN:  moveDown();  break;
111     case CMD_LEFT:  moveLeft();  break;
112     case CMD_RIGHT: moveRight(); break;
113     }
114     createNum();
115     createNum();
116     step++;
117 }
118 
119 void GameLogic::moveUp()
120 {
121     for(int j=0; j<COL; j++)
122     {
123         //取出全部非零元素
124         int t[10] = {0};
125         int cnt = 0;
126         for(int i=0; i<ROW; i++)
127             if(data[i][j])
128                 t[cnt++] = data[i][j];
129 
130         for(int k=0; k<cnt-1; k++)
131         {
132             if(t[k]==t[k+1])
133             {
134                 gradeBasic += t[k];
135                 t[k] *= 2;
136                 t[k+1] = 0;
137             }
138         }
139         //將合併後的非零元素填入data中
140         int n = 0;
141         for(int k=0; k<cnt; k++)
142         {
143             if(t[k])
144                 data[n++][j] = t[k];
145         }
146         //尾部補零
147         for(; n<ROW; n++)
148         {
149             data[n][j] = 0;
150         }
151     }
152 }
153 
154 void GameLogic::moveDown()
155 {
156     for(int j=0; j<COL; j++)
157     {
158         int t[10];
159         int cnt = 0;
160 
161         for(int i=ROW-1; i>=0; i--)
162             if(data[i][j])    t[cnt++] = data[i][j];
163 
164         for(int k=0; k<cnt-1; k++)
165         {
166             if(t[k]==t[k+1])
167             {
168                 gradeBasic += t[k];
169                 t[k] *= 2;
170                 t[k+1] = 0;
171             }
172         }
173 
174         int n = ROW-1;
175         for(int k=0; k<cnt; k++)
176         {
177             if(t[k])    data[n--][j] = t[k];
178         }
179 
180         for(; n>=0; n--)
181         {
182             data[n][j] = 0;
183         }
184     }
185 }
186 
187 void GameLogic::moveLeft()
188 {
189     for(int i=0; i<ROW; i++)
190     {
191         int t[10];
192         int cnt = 0;
193         for(int j=0; j<COL; j++)
194             if(data[i][j])    t[cnt++] = data[i][j];
195 
196         for(int k=0; k<cnt-1; k++)
197         {
198             if(t[k]==t[k+1])
199             {
200                 gradeBasic += t[k];
201                 t[k] *= 2;
202                 t[k+1] = 0;
203             }
204         }
205 
206         int n = 0;
207         for(int k=0; k<cnt; k++)
208         {
209             if(t[k])    data[i][n++] = t[k];
210         }
211 
212         for(; n<COL; n++)
213         {
214             data[i][n] = 0;
215         }
216 
217     }
218 }
219 
220 void GameLogic::moveRight()
221 {
222     for(int i=0; i<ROW; i++)
223     {
224         int t[10];
225         int cnt = 0;
226         for(int j=COL-1; j>=0; j--)
227             if(data[i][j])    t[cnt++] = data[i][j];
228 
229         for(int k=0; k<cnt-1; k++)
230         {
231             if(t[k]==t[k+1])
232             {
233                 gradeBasic += t[k];
234                 t[k] *= 2;
235                 t[k+1] = 0;
236             }
237         }
238 
239         int n = COL-1;
240         for(int k=0; k<cnt; k++)
241         {
242             if(t[k])    data[i][n--] = t[k];
243         }
244 
245         for(; n>=0; n--)
246         {
247             data[i][n] = 0;
248         }
249 
250     }
251 }
252 
253 int GameLogic::judge()
254 {
255     //贏得遊戲
256     for (int i=0; i<ROW; i++)
257     {
258         for (int j=0; j<COL; j++)
259         {
260             if (data[i][j] == 2048)
261             {
262                 return STAT_WIN;
263             }
264         }
265     }
266     //橫向檢查
267     for (int i=0; i<ROW; i++)
268     {
269         for (int j=0; j<COL-1; j++)
270         {
271             if (!data[i][j] || (data[i][j] == data[i][j+1]))
272             {
273                 return STAT_PROCESS;
274             }
275         }
276     }
277     //縱向檢查
278     for (int j=0; j<COL; j++)
279     {
280         for (int i=0; i<ROW-1; i++)
281         {
282             if (!data[i][j] || (data[i][j] == data[i+1][j]))
283             {
284                 return STAT_PROCESS;
285             }
286         }
287     }
288     //不符合上述兩種情況,遊戲結束
289     return STAT_LOSE;
290 }
291 
292 bool GameLogic::getGameStart(){return gameStart;}
293 void GameLogic::setGameStart(bool flag){gameStart = flag;}
294 void GameLogic::setGradeUpCoefficient(float i){gradeUpCoefficient = i;}
295 int GameLogic::getData(int i, int j){return data[i][j];}
296 int GameLogic::getGrade(){return grade;}
297 int GameLogic::getGradeBasic(){return gradeBasic;}
298 int GameLogic::getGradeUp(){return gradeUp;}
299 int GameLogic::getStep(){return step;}
View Code
 ① 宏定義棋盤行列數:#define ROW 4;  #define COL 4;
 ② 枚舉定義指令與狀態:enum CMD...  enum STAT...
 ③ 定義成員變量:
    遊戲狀態:bool gameStart;
    棋盤規格:int data[ROW][COL];
    分數統計:float grade;
         int gradeBasic;
        float gradeUp;
        float gradeUpCoefficient;
    當前步數:int step;
   隨機數機率:int prob2;
         int prob4;
         int prob8;
         int prob16;
 ④ 定義成員函數:
   初始化數據:void initAll();
    創造隨機數:bool createNum();
    狀態斷定:int judge();
   機率計算:void calProb();
     遊戲過程:void process(int cmd);
         void moveUp();
         void moveDown();
         void moveLeft();
         void moveRight();
    數據處理:bool getGameStart();
         void setGameStart(bool);
         void setGradeUpCoefficient(float);
         int getData(int,int);
         int getGrade();
         int getGradeBasic();
         int getGradeUp();
         int getStep();
相關文章
相關標籤/搜索