Qt项目实战二(2048小游戏加炸弹的纯代码实现)

这个程序由于我中间丢失过代码,所以构思稍微有点混乱,算法和主体部分放在了game类中实现。

数据保存,只存了分数,并且也为做优化,所以有瑕疵。

总体分为初始界面,游戏界面,数据保存三块。不多说上代码:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "game.h"
#include "QPushButton"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT
    game* G;
    QPushButton* startbutton;
    QPushButton* closebutton;
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    
private slots:
//按钮的槽函数
    void start_clicked();

    void close_clicked();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    startbutton =new QPushButton(this);
    startbutton->setText("STARTGAME");
    startbutton->move(150,100);
    startbutton->setFlat(true);//就是这句实现按钮透明的效果。
    closebutton =new QPushButton(this);
    closebutton->setText("EXITGAME");
    closebutton->move(150,150);
    closebutton->setFlat(true);//就是这句实现按钮透明的效果。
    connect(startbutton,SIGNAL(clicked()),this,SLOT(start_clicked()));
    connect(closebutton,SIGNAL(clicked()),this,SLOT(close_clicked()));



    //setStyleSheet("QWidget{border-image: url(:/new/prefix1/2048.jpg);}");
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::start_clicked()
{
    G=new game(this);
    G->resize(500,500);
    G->show();

}

void MainWindow::close_clicked()
{
    close();
}

这里用纯代码编写,有点复杂,在移动控件时比较复杂,建议大家使用代码与画布的联合使用,会比较容易。

代码与算法主体GAME:

#ifndef GAME_H
#define GAME_H

#include <QMainWindow>
#include <QLabel>
#include <QTime>
#include <QFont>
#include <QPalette>
#include <QObject>
#include <QKeyEvent>
#include <QLCDNumber>
#include <QEvent>
#include <QHash>
#include <QLayout>
#include <QString>
#include <QPushButton>
#include <vector>
#include <iostream>
#include "datasave.h"
class game : public QMainWindow
{
    Q_OBJECT
    QLCDNumber* steplcd;
    QLCDNumber* scorelcd;
    QLCDNumber* maxscorelcd;
    QLabel* maxscorelabel;
    QLabel* msg;
    datasave* data;
public:
    explicit game(QWidget *parent = 0);
    ~game(void);
    //分数容器,用来排名
    std::vector<int> grade;
    //开始游戏
    void newgame();
    //初始化表格
    void setpane();
    //判断棋盘中空格个数
    int space_num();
    //随机出棋盘中两个2
    void srand_twonew();
    //初始化Label的值
    void setLabel(void);
    //放置label的位置
    void setposlabel(void);

    void upmove(); //上移

    void downmove(); //下移

    void leftmove(); //左移

    void rightmove(); //右移
    void keyPressEvent(QKeyEvent *event);

    void upremoveblank();

    void downremoveblank();

    void leftremoveblank();

    void rightremoveblank();

    bool testup(); //能否上移测试

    bool testdown(); //能否上移测试

    bool testright(); //能否上移测试

    bool testleft(); //能否上移测试
    int panemax(); //棋盘最大数
    void sumscore(); //总分数

    bool ifwin(); //判断是否胜利

    bool ifGameOver();  //判断是否游戏结束

    void update(const int& t);
    //设置数字背景色,根据数字不同
    void set_back(int i,int j);
    //获取炸弹,并且将背景设置为炸弹,添加炸弹按钮
    void get_boom(void);

    //求最大分数
    int maxscore(void);
private:

    int pane[4][4];
    QHash<int,QLabel*> labelHash;
    QGridLayout* layout;
    QLabel* label[16];
    QWidget * widget;
    QPushButton* boombutton;
    int stepcount;

    int score;
public slots:
    void set_boom();

};

#endif // GAME_H

可以看出头文件就很复杂,因为每一个控件都是用代码添加,所以比较繁琐。

#include "game.h"
#include <QLabel>
#include <QPushButton>


game::game(QWidget *parent) :
    QMainWindow(parent)
{
    data=new datasave;
    data->load(grade);
   // qDebug("-----grade:%d",grade.size());

    layout=new QGridLayout;
    widget=new QWidget(this);
    steplcd=new QLCDNumber(this);
    scorelcd=new QLCDNumber(this);
    maxscorelcd=new QLCDNumber(this);
    setStyleSheet("QMainWindow{border-image: url(:/new/prefix1/1111.jpg);}");

    QLabel* stepnum=new QLabel(this);
    QLabel* scorenum=new QLabel(this);
    maxscorelabel=new QLabel(this);
    boombutton=new QPushButton(this);
    boombutton->hide();

    msg=new QLabel(this);
    msg->move(10,40);
    msg->hide();

    maxscorelabel->setText("MAX:");
    stepnum->setText("STEP:");
    scorenum->setText("SCORE:");
    maxscorelabel->move(100,30);
    stepnum->move(260,30);
    scorenum->move(260,60);
    stepcount=0;
    score=0;
    maxscorelcd->move(150,30);
    steplcd->move(310,30);
    scorelcd->move(310,60);
    newgame();
    stepcount=0;
    score=0;

}
game::~game()
{
    data->save(grade);
    delete data;
    
}

//初始化表格
void game::setpane()
{
    QTime time;
    time = QTime::currentTime();

    qsrand(time.msec()+time.second()*1000);

    for(int i=0;i<=3;i++) //初始化棋盘

       for(int j=0;j<=3;j++)
       {

            pane[i][j]=0;
        }
       int m=qrand()%4;
       int n=qrand()%4;
       int b=qrand()%4;
       int q=qrand()%4;
       pane[m][n]=pane[b][q]=2;
}

//判断棋盘中空格个数
int  game::space_num()
{
    int num=0;
    for(int i=0;i<4;i++)
    {
        for(int j=0;j<4;j++)
        {
            if(pane[i][j]==0)
            {
                num++;
            }
        }
    }
    return num;
}

//随机出棋盘中两个2
void  game::srand_twonew()
{
    QTime time;
    time = QTime::currentTime();
    qsrand(time.msec()+time.second()*1000);
    if(space_num()>=2)
    {
        int count=2;
        while(count>0)
        {
            int m=qrand()%4;
            int n=qrand()%4;
            if(pane[m][n]==0)
            {
                pane[m][n]=2;
                count--;
            }
        }
    }
    else if(space_num()==1)
    {
        int num=1;
        while(num>0)
        {
            int m=qrand()%4;
            int n=qrand()%4;
            if(pane[m][n]==0)
            {
                pane[m][n]=2;
                num--;
            }
        }
    }
}

//初始化Label的值
void  game::setLabel(void)
{
    for(int i=0;i<16;i++)
    {
        label[i]=new QLabel;
        labelHash.insert(i,label[i]);
    }


}

//放置label的位置
void  game::setposlabel(void)
{
    for(int i=0;i<16;i++)

    {

            labelHash.value(i)->setFrameShape(QLabel::Box);

            labelHash.value(i)->setText(" ");

            layout->addWidget(labelHash.value(i),i/4,i%4,1,1);

    }

        layout->setSpacing(4);

        widget->setLayout(layout);

        widget->resize(300,300);
        widget->move(115,90);


}


//开始游戏
void  game::newgame()
{
    setpane();
    setLabel();
    setposlabel();
    //ui->pushButton->close();
    update(0);

}

//上移
void  game::upmove()
{
    for(int j=0;j<4;j++){//每一列

             for(int i=0;i<3;i++){

                 if(pane[i][j]==pane[i+1][j]){

                     pane[i][j]=pane[i][j]+pane[i+1][j];

                     pane[i+1][j]=0;

                     //移除空格

                     upremoveblank();

                 }

             }

         }
}

//下移
void  game::downmove()
{
    for(int j=0;j<4;j++){//每一列

          for(int i=3;i>=1;i--){

              if(pane[i][j]==pane[i-1][j]){

                  pane[i][j]=pane[i][j]+pane[i-1][j];

                  pane[i-1][j]=0;

                  //移除空格

                  downremoveblank();

              }

          }

      }
}

//左移
void  game::leftmove()
{
    for(int i = 0;i < 4;i++){

           for(int j = 0;j<3;j++){

               if(pane[i][j]==pane[i][j+1]){

                   pane[i][j]+=pane[i][j+1];

                   pane[i][j+1]=0;

                   leftremoveblank();

               }

           }

       }
}

//右移
void  game::rightmove()
{
    for(int i=0;i<4;i++){

            for(int j=3;j >= 1;j--){

                if(pane[i][j]==pane[i][j-1]){

                    pane[i][j]+=pane[i][j-1];

                    pane[i][j-1]=0;

                    rightremoveblank();

                }

            }

        }
}

void  game::keyPressEvent(QKeyEvent *event)
{
    if(!ifGameOver())
    {
        msg->setText("Game Over!");
        msg->show();
        return;
    }
    switch (event->key()) {

        case Qt::Key_W:
           // get_boom();
            if(!testup()) return;

            upremoveblank();

            upmove();
            sumscore();
            srand_twonew();

            stepcount++;

            update(stepcount);

            break;

        case Qt::Key_S:
        if(!testdown()) return;

            downremoveblank();

            downmove();
            sumscore();
            srand_twonew();

            stepcount++;

            update(stepcount);

            break;

        case Qt::Key_A:
        if(!testleft()) return;


            leftremoveblank();

            leftmove();

             sumscore();
            srand_twonew();

            stepcount++;

            update(stepcount);



            break;

        case Qt::Key_D:
        if(!testright()) return;
            rightremoveblank();

            rightmove();
            sumscore();
            srand_twonew();
            stepcount++;

            update(stepcount);
            break;

        default:

            break;

        }
}

void  game::upremoveblank()
{
    for(int j=0;j<4;j++){

            int k = 0;

            for(int i=0;i<4;i++){

                if(pane[i][j] != 0)
                {

                    pane[k++][j] = pane[i][j];
                }

                }

            while(k<4)

            {

                pane[k][j] = 0;

                k++;

            }

        }
}

void  game::downremoveblank()
{  for(int j=0;j<4;j++){

        int k = 3;

        for(int i=3;i>=0;i--){

            if(pane[i][j] != 0)

                pane[k--][j] = pane[i][j];

            }

        while(k>=0)

        {

            pane[k][j] = 0;

            k--;

        }

    }
}

void  game::leftremoveblank()
{
    for(int i=0;i<4;i++){

           int k = 0;

           for(int j=0;j<4;j++){

               if(pane[i][j] != 0)

                   pane[i][k++] = pane[i][j];

               }

           while(k<4)

           {

               pane[i][k] = 0;

               k++;

           }

       }
}

void  game::rightremoveblank()
{
    for(int i=0;i<4;i++){

            int k = 3;

            for(int j=3;j>=0;j--){

                if(pane[i][j] != 0)

                    pane[i][k--] = pane[i][j];

                }

            while(k>=0)

            {

                pane[i][k] = 0;

                k--;

            }

        }
}

//能否上移测试
bool  game::testup()
{


    for(int j=0;j<=3;j++)

        for(int i=0;i<3;i++)

        {

            if(pane[i][j] == pane[i+1][j] || pane[i][j] == 0)

            {

              return true;

            }

        }

    return false;
}

//能否下移测试
bool  game::testdown()
{


        for(int j=0;j<=3;j++)

            for(int i=3;i>0;i--)

            {

                if(pane[i][j] == pane[i-1][j] || pane[i][j] == 0)

                {

                     return true;

                }

            }

        return false;
}

//能否右移测试
bool  game::testright()

{


       for(int i=0;i<=3;i++)

           for(int j=3;j>0;j--)

           {

              if(pane[i][j] == pane[i][j-1] || pane[i][j] == 0)

               {

                    return true;

               }

           }

       return false;
}

//能否左移测试
bool  game::testleft()
{


        for(int i=0;i<=3;i++)

            for(int j=0;j<3;j++)

            {

               if(pane[i][j] == pane[i][j+1] || pane[i][j] == 0)

                {

                     return true;

                }

            }

        return false;
}

//棋盘最大数
int  game::panemax()
{
   int max=0;
   for(int i=0;i<4;i++)
   {
       for(int j=0;j<4;j++)
       {
           if(pane[i][j]>max)
           {
               max=pane[i][j];
           }
       }
   }
   return max;
}

//总分数
void  game::sumscore()
{

    score+=panemax();

}
 //判断是否胜利
bool  game::ifwin()
{
    for(int i=0;i<4;i++)
    {
        for(int j=0;j<4;j++)
        {
            if(pane[i][j]==2048)
            {
                return true;
            }
        }
    }
    return false;
}

//判断是否游戏结束
bool  game::ifGameOver()
{
    if((testup()+testdown()+testright()+testleft())==0)
    {
        return false;
    }
    return true;
}

void  game::update(const int& t)
{

    for(int i = 0 ; i < 4 ; i++)
    {
           for(int j = 0; j < 4; j++)

           {

               int p = i*4+j;

               if(pane[i][j])

               {

                   labelHash.value(p)->setText(QString::number(pane[i][j]));

               }

               else
               {

                    labelHash.value(p)->setText(" ");
               }
               QFont ftt;

               ftt.setPointSize(24);

               labelHash.value(p)->setFont(ftt);

               QPalette pa;

               pa.setColor(QPalette::WindowText,Qt::white);

               labelHash.value(p)->setPalette(pa);

               labelHash.value(p)->setAlignment(Qt::AlignCenter);
               set_back(i,j);

               //labelHash.value(p)->setStyleSheet("background-color: rgb(170, 255, 255);");

           }
         steplcd->display(QString::number(stepcount));
         scorelcd->display(QString::number(score));
         maxscorelcd->display((QString::number(maxscore())));
         grade.push_back(maxscore());
    }
}
 void game::set_back(int i,int j)
 {
     int p=i*4+j;
     switch(pane[i][j])
     {
       case 0: labelHash.value(p)->setStyleSheet("background-color: rgb(97, 0, 0);");break;
       case 2: labelHash.value(p)->setStyleSheet("background-color: rgb(100, 170, 127);");break;
       case 4: labelHash.value(p)->setStyleSheet("background-color: rgb(255, 100, 127);");break;
       case 8: labelHash.value(p)->setStyleSheet("background-color: rgb(85, 170, 0);");break;
       case 16:labelHash.value(p)->setStyleSheet("background-color: rgb(170, 85, 255);");break;
       //border-image: url(:/new/prefix1/1024.jpg);background-color: rgb(170, 85, 255);
       case 32: labelHash.value(p)->setStyleSheet("background-color: rgb(170, 85, 255);");break;
       case 64: labelHash.value(p)->setStyleSheet("background-color: rgb(85, 270, 0);");break;
       case 128: labelHash.value(p)->setStyleSheet("background-color: rgb(170, 85, 255);");  break;
       case 256: labelHash.value(p)->setStyleSheet("border-image: url(:/new/prefix1/1024.jpg)"); get_boom(); break;
       case 512: labelHash.value(p)->setStyleSheet("background-color: rgb(85, 170, 0);");;break;
       case 1024: labelHash.value(p)->setStyleSheet("background-color: rgb(85, 170, 0);");break;
       case 2048: labelHash.value(p)->setStyleSheet("background-color: rgb(255, 255, 127);");break;
       case 4096: labelHash.value(p)->setStyleSheet("background-color: rgb(97, 0, 0);");break;
       case 8192: labelHash.value(p)->setStyleSheet("background-color: rgb(90, 90, 90);");break;

      }
 }
 //获取炸弹,并且将背景设置为炸弹,添加炸弹按钮
void game::get_boom(void)
{
    //qDebug("----------");
   // boombutton=new QPushButton(this);
    boombutton->move(10,10);
    boombutton->setText("BOOM");
    boombutton->setStyleSheet("background-color: rgb(97, 0, 0);");
    connect(boombutton,SIGNAL(clicked()),this,SLOT(set_boom()));
    boombutton->show();
}
//按下按钮炸掉炸弹,炸掉自己
void game::set_boom()
{
    boombutton->hide();
    for(int i=0;i<4;i++)
    {
        for(int j=0;j<4;j++)
        {
            if(pane[i][j]==256)
            {
                pane[i][j]=0;
            }
        }
    }
    update(score);
}
//求最大分数
int game::maxscore(void)
{
    int s=0;
    for(unsigned int i=0;i<grade.size();i++)
    {
        if(s<grade[i])
        {
            s=grade[i];
        }
    }
    if(s>score)
    {
        return s;
    }
    else
    {
        return score;
    }

}

有些地方注释写的不够明白,因为数据丢失,所以我反复写的时候就没给出很详细的注释,set_back部分,是根据数字的不同设置不同的背景色!

炸弹是通过按钮实现的,当出现炸弹时按钮也会出现,可以引爆,最大分数更新稍微有点浪费存储控件,未作出优化,优化方法较为简单,这里就不过多赘述。

#ifndef DATASAVE_H
#define DATASAVE_H

#include <QObject>
//#include "game.h"
#include <vector>
#include <iostream>
using namespace std;

class datasave : public QObject
{
    Q_OBJECT
public:
    explicit datasave(QObject *parent = 0);
    void load(vector<int>& grade);
    void save(vector<int>& grade);
    
signals:
    
public slots:
    
};

#endif // DATASAVE_H
#include "datasave.h"
#include <fstream>
#include <iostream>
using namespace std;

datasave::datasave(QObject *parent) :
    QObject(parent)
{
}
void datasave::load(vector<int>& grade)
{
    ifstream in;
    in.open("./score.dat",ios::binary);
    int  s;
    // qDebug("-------------load:%d",grade.size());
    while(in.read((char*)&s,sizeof(int)))
    {
         grade.push_back(s);
    }
    // qDebug("-------------load:%d",grade.size());
}

void datasave::save(vector<int>& grade)
{
    ofstream out;
    //qDebug("-------------save:%d",grade.size());
    out.open("./score.dat",ios::binary);
        for(unsigned int i=0;i<grade.size();i++)
        {
            out.write((char*)&grade[i],sizeof(int));
        }
}

数据读写,就最基础的存储方式。

整个程序比较简单,不过算法方面都是比较成熟的,所以大家可以取其精华,去其糟粕。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值