qt制作扫雷

作者: 唐宇威威 | 来源:发表于2016-12-30 14:04 被阅读411次

    沉默了一周我终于复活了,这回给大家带来的是扫雷。先说明一下,这个扫雷是我在ubuntu下用c++编写,qt制作的,如果windows系统需要用qt在windows下编译生成的.exe文件才能运行。而且用到了一些控件所以有些代码不能直接复制使用。如果有需要的朋友可以评论留邮箱我把整个项目发过去,虽然做的很一般。话不多说先看几个截图。


    初始界面没做好,只能点easy正确,难度在后面改。


    开始界面

    点开easy后出现了我们游戏界面,8x8 8个雷。基本扫雷的操作都有,不解释了,直接上图。

    简单模式 选哪个好啊 炸了 终于赢了

    左上角的菜单里有选项可以重开,选择难度,结束游戏。
    下面是代码,分的文件比较多。
    mainwindow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    #include"myscene.h"
    #include <QMainWindow>
    
    namespace Ui {
    class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = 0);
        virtual ~MainWindow();
    
    private slots:
        void on_actionExit_triggered();
    
        void on_actionRestart_triggered();
    
        void on_actionHard_triggered();
    
        void on_actionEx_triggered();
    
        void on_actionEasy_triggered();
    
    private:
        Ui::MainWindow *ui;
        myscene sc;
    };
    
    #endif // MAINWINDOW_H
    
    

    myitem.h//单位的头文件

    #ifndef MYITEM_H
    #define MYITEM_H
    #include<unistd.h>
    
    #include <QGraphicsPixmapItem>
    #include <QCloseEvent>
    
    class myitem : public QGraphicsPixmapItem
    {
    public:
        int aright;//判断右键点击次数
        int aleft;//判断左键是否点击过
        myitem(int x,int y);
       virtual  ~myitem(){}
    protected:
        int m_x;
        int m_y;
        void  mousePressEvent(QGraphicsSceneMouseEvent *event);
        void  mousePressEvent2();
        void  gameover();
    
    };
    
    #endif // MYITEM_H
    
    

    myscene.h//场景,地图

    #ifndef MYSCENE_H
    #define MYSCENE_H
    #include<vector>
    #include<myitem.h>
    #include <QGraphicsScene>
    using namespace std;
    
    typedef vector<myitem*> irow;
    typedef vector<irow> imap;
    class myscene : public QGraphicsScene
    {
        Q_OBJECT
    public:
        explicit myscene(QObject *parent = 0);
        virtual ~myscene(){removeAllTheiMx();}
        imap iMx;
        void removeAllTheiMx();
        void resetAllTheiMx();
    signals:
        
    public slots:
    private:
    
        
    };
    
    #endif // MYSCENE_H
    
    

    startgame.h

    #ifndef STARTGAME_H
    #define STARTGAME_H
    
    #include <QDialog>
    #include <QMainWindow>
    #include"mainwindow.h"
    #include<QDebug>
    
    namespace Ui {
    class startgame;
    }
    
    class startgame : public QDialog
    {
        Q_OBJECT
    
    public:
        explicit startgame(QWidget *parent = 0);
        virtual ~startgame();
    
    private slots:
        void on_pusheasy_clicked();
    
        void on_pushnormal_clicked();
    
    private:
        Ui::startgame *ui;
    };
    
    #endif // STARTGAME_H
    
    

    tywmodel.h//布雷

    #ifndef TYWMODEL_H
    #define TYWMODEL_H
    #include<vector>
    using namespace std;
    typedef vector<int> mrow;
    typedef vector<mrow> mmap;
    class tywmodel
    {
    public:
        tywmodel();
        virtual ~tywmodel(){mMx.clear();}
        mmap mMx;
        void tywclear();//清理地雷用于重置前
        void tywreset();//重置地雷
    };
    
    #endif // TYWMODEL_H
    
    

    main.cpp

    #include "mainwindow.h"
    #include <QApplication>
    #include"tywmodel.h"
    #include"startgame.h"
    int tywwidth=8;//第一次打开时默认简单模式的数据,宽度
    int tywlength=8;//高度,竖着的
    int tywtrap=8;//地雷数量
    int win=56;//胜利条件,56个非雷区域被点开
    int nandu=1;//一开始用于记录难度,后来直接用做判断是否踩过雷
    tywmodel m;//一个雷的二维容器
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        startgame q;//显示第一个窗口,其实这个没啥用,可以注掉这行和下一行
        q.exec();//阻塞显示q,q不关后面不出来。
        MainWindow w;
        w.show();
    
        return a.exec();
    }
    
    

    mainwindow.cpp

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include "myscene.h"
    #include"myitem.h"
    #include "tywmodel.h"
    #include <stdlib.h>
    #include <time.h>
    extern int tywwidth;
    extern int tywlength;
    extern int win;
    extern int tywtrap;
    extern int nandu;
    extern tywmodel m;
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        ui->graphicsView->setScene(&sc);
        sc.setSceneRect(sc.itemsBoundingRect());// 下面3行代码是自动调整窗口大小自适应的
        ui->graphicsView->setFixedSize(sc.sceneRect().width() +5,sc.sceneRect().height()+5);
        this->resize(ui->graphicsView->width(),ui->graphicsView->height()+ 39);
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    void MainWindow::on_actionExit_triggered()
    {
        close();
    }
    
    void MainWindow::on_actionRestart_triggered()//点击重新开始
    {
        win=tywlength*tywlength-tywtrap;
        sc.removeAllTheiMx();//先清除之前的东西
        m.tywclear();
        nandu=1;
        sc.resetAllTheiMx();//再赋值
        m.tywreset();
    
    }
    
    void MainWindow::on_actionHard_triggered()
    {    
            sc.removeAllTheiMx();
            m.tywclear();
            tywwidth=16;//数据必须在这里改,如果放在前面,清除时对应不上出错
            tywlength=12;
            tywtrap=40;
            nandu=2;
            win=tywwidth*tywlength-tywtrap;//重置胜利条件
            sc.resetAllTheiMx();
            m.tywreset();
            sc.setSceneRect(sc.itemsBoundingRect());// xiamian 3 hang zi dong tiaozheng chuangkou daxiao
            ui->graphicsView->setFixedSize(sc.sceneRect().width() +5,sc.sceneRect().height()+5);
            this->resize(ui->graphicsView->width(),ui->graphicsView->height()+ 39);
    }
    
    void MainWindow::on_actionEx_triggered()//ex难度,后面也是不同难度而已
    {
    
    sc.removeAllTheiMx();
    m.tywclear();
    tywwidth=25;
    tywlength=20;
    tywtrap=110;
     win=tywwidth*tywlength-tywtrap;
    nandu=3;
    sc.resetAllTheiMx();
    m.tywreset();
    sc.setSceneRect(sc.itemsBoundingRect());// xiamian 3 hang zi dong tiaozheng chuangkou daxiao
    ui->graphicsView->setFixedSize(sc.sceneRect().width() +5,sc.sceneRect().height()+5);
    this->resize(ui->graphicsView->width(),ui->graphicsView->height()+ 39);
    }
    
    void MainWindow::on_actionEasy_triggered()
    {
        sc.removeAllTheiMx();
        m.tywclear();
        tywwidth=8;
        tywlength=8;
        tywtrap=8;
        nandu=1;
        win=tywwidth*tywlength-tywtrap;
        sc.resetAllTheiMx();
        m.tywreset();
        sc.setSceneRect(sc.itemsBoundingRect());// xiamian 3 hang zi dong tiaozheng chuangkou daxiao
        ui->graphicsView->setFixedSize(sc.sceneRect().width() +5,sc.sceneRect().height()+5);
        this->resize(ui->graphicsView->width(),ui->graphicsView->height()+ 39);
    }
    
    

    myitem.cpp 单位控制,单独一个格子的设定。

    #include "myitem.h"
    #include<QPixmap>
    #include<QGraphicsSceneMouseEvent>
    #include<QMessageBox>
    #include<QDebug>
    #include "tywmodel.h"
    #include"myscene.h"
    extern tywmodel m;
    extern int tywwidth;
    extern int tywlength;
    extern int win;
    extern int tywtrap;
    extern int nandu;
    myitem::myitem(int x,int y)
    {
        QPixmap t("mine2.png");
        m_x=x;m_y=y;
        aright=0;
        aleft=0;
        setPixmap(t);
    }
    //鼠标点击事件
    void myitem:: mousePressEvent(QGraphicsSceneMouseEvent *event)
    {   
         ((myscene*)scene())->iMx;
        if(aleft==1)//判断是否被左键点击过
        {
            return;//是,返回不屌
        }
        if(event->button()==Qt::LeftButton)//如果是左键点击
        {     
            mousePressEvent2();//调用函数,单独写出去方便递归
        }
        if(event->button()==Qt::RightButton)  //  右键点击
        {
            if(aright==0)//没点击过插旗,点击过取消小旗
            {
                QPixmap t("miner.png");
                setPixmap(t);
                aright=1;
            }
            else
            {
                QPixmap t("mine2.png");
                setPixmap(t);
                aright=0;
            }
        }
    }
    
    void myitem:: mousePressEvent2()
    {
        int i=0,j=0;
        if(aleft==1)
        {
            return;
        }
         aleft=1;
         switch(m.mMx[m_x][m_y])//判断是什么并显示对应图片
         {
         case 0:
         {
             QPixmap t("mine0.png");
             setPixmap(t);win--;break;
         }
         case 1:
         {
             QPixmap t("1.png");
             setPixmap(t);win--;break;
         }
         case 2:
         {
             QPixmap t("2.png");win--;
             setPixmap(t);break;
         }
         case 3:
         {
             QPixmap t("3.png");win--;
             setPixmap(t);break;
         }
         case 4:
         {
             QPixmap t("4.png");win--;
             setPixmap(t);break;
         }
         case 5:
         {
             QPixmap t("5.png");win--;
             setPixmap(t);break;
         }
         case 6:
         {
             QPixmap t("6.png");win--;
             setPixmap(t);break;
         }
         case 7:
         {
             QPixmap t("7.png");win--;
             setPixmap(t);break;
         }
         case 8:
         {
             QPixmap t("8.png");win--;
             setPixmap(t);break;
         }
         case -1:
         {
             QPixmap t("BOOM.png");
             setPixmap(t);break;
         }
         }
         if(win==0)//胜利
         {
             if(nandu != 0)//没有踩过雷
    //时间后来忘做了,加一个计时器就好了。这里时间显示是固定的(假的)
             {QMessageBox::Cancel==QMessageBox::information(NULL,"You win","time 00:48",QMessageBox::Cancel|QMessageBox::Ok);}
         }
        if(m.mMx[m_x][m_y]==0)//如果是0对周围自动展开
        {
            int myrow;
            int mycolumn;
            for(i=-1;i<2;i++)
            {
                for(j=-1;j<2;j++)
                {
                    if(i==0&&j==0)
                        continue;
                    myrow=m_x+i;
                    mycolumn=m_y+j;
    //防止越界进行判断
                    if(myrow<0||mycolumn<0||myrow>=tywwidth||mycolumn>=tywlength)
                        continue;
                    ((myscene*)scene())->iMx[myrow][mycolumn]->mousePressEvent2();
                  }
            }
        }
         if(m.mMx[m_x][m_y]==-1)//踩雷,触发游戏结束函数
         {
             win+=100;
             if(nandu==0)
                 return;
             gameover();
         }
    
    }
    void myitem::gameover()//打开所有格子,提示重新开始
    {
        int i,j;
        nandu=0;
        int myrow,mycolumn;
        for(i=0;i<tywwidth;i++)
        {
            for(j=0;j<tywlength;j++)
            {
                myrow=i;
                mycolumn=j;
                if(myrow<0||mycolumn<0||myrow>=tywwidth||mycolumn>=tywlength)
                    continue;
                ((myscene*)scene())->iMx[myrow][mycolumn]->mousePressEvent2();
              }
        }
        QMessageBox::Cancel==QMessageBox::information(NULL,"You lose","Please restart!",QMessageBox::Cancel|QMessageBox::Ok);
    
    }
    
    

    myscene.cpp 场景

    #include "myscene.h"
    #include"myitem.h"
    extern int tywwidth;
    extern int tywlength;
    myscene::myscene(QObject *parent) :
        QGraphicsScene(parent)
    {
        int i,j;//按照给定的全局变量长宽摆放各个单位格子
        for(i=0;i<tywwidth;i++)
        {
            iMx.push_back(irow(tywlength));
            for(j=0;j<tywlength;j++)
            {
                iMx[i][j] = new myitem(i,j);
                iMx[i][j]->setPos(iMx[i][j]->boundingRect().width()*i, iMx[i][j]->boundingRect().height()*j);
                addItem(iMx[i][j]);
            }
        }
    }
    void myscene::removeAllTheiMx()//清除所有格子,才能重来
    {
        for(int i=0;i<tywwidth;i++)
        {
            for(int j=0;j<tywlength;j++)
            {
                removeItem(iMx[i][j]);
                delete iMx[i][j];
            }
        }
        iMx.clear();
    }
    void myscene::resetAllTheiMx()//重新造,代码重复可以整理。
    {
        int i,j;
        for(i=0;i<tywwidth;i++)
        {
            iMx.push_back(irow(tywlength));
            for(j=0;j<tywlength;j++)
            {
                iMx[i][j] = new myitem(i,j);
                iMx[i][j]->setPos(iMx[i][j]->boundingRect().width()*i, iMx[i][j]->boundingRect().height()*j);
                addItem(iMx[i][j]);
            }
        }
    }
    
    
    

    startgame.cpp 这个可以无视掉,没啥大用。

    #include "startgame.h"
    #include "ui_startgame.h"
    #include <QLabel>
    #include <QMovie>
    #include"tywmodel.h"
    extern int tywwidth;
    extern int tywlength;
    extern int tywtrap;
    extern int win;
    extern int nandu;
    extern tywmodel m;
    startgame::startgame(QWidget *parent) :
        QDialog(parent),
        ui(new Ui::startgame)
    {
        ui->setupUi(this);
        QMovie *movie =new QMovie("fm2.png");
        ui->label->setMovie(movie);
        movie->start();
    }
    
    startgame::~startgame()
    {
        delete ui;
    }
    
    void startgame::on_pusheasy_clicked()
    {
        close();
    }
    
    void startgame::on_pushnormal_clicked()
    {
        close();
    }
    
    

    tywmodel.cpp 布置地雷(具体哪个是雷)

    #include "tywmodel.h"
    #include "myscene.h"
    #include"myitem.h"
    #include <stdlib.h>
    #include <time.h>
    extern int tywwidth;
    extern int tywlength;
    extern int tywtrap;
    int suiji(int a)//取1-a的随机整数。这个可以不用。
    {
        int rp;
        int i = 0;
        while (i < 10){
            srand((unsigned)time(NULL));
            rp = 1 + rand() % a;
            i++;
        }
        return rp;
    }
    tywmodel::tywmodel()  //先创造二维容器vector
    {
        for(int i= 0;i<tywwidth;i++)
        {
            mMx.push_back(mrow(tywlength));
            for(int j=0;j<tywlength;j++)
            {
                mMx[i][j] = 0;
            }
        }
        srand(time(NULL));随机
        for(int i=0;i<tywtrap;)
        {
            int x = rand()%tywwidth;
            int y = rand()%tywlength;
            if(mMx[x][y]!=-1)
            {
                i++;mMx[x][y]=-1;//如果是雷,对周围格子+1,需判断是否越界,是否周围是雷(雷不能+1,-1是雷)
                if((x-1>=0)&&(x-1<tywwidth)&&(y-1>=0)&&(y-1<tywlength)&&(mMx[x-1][y-1]!=-1))mMx[x-1][y-1]++;
                if((x-1>=0)&&(x-1<tywwidth)&&(y>=0)&&(y<tywlength)&&(mMx[x-1][y]!=-1))mMx[x-1][y]++;
                if((x-1>=0)&&(x-1<tywwidth)&&(y+1>=0)&&(y+1<tywlength)&&(mMx[x-1][y+1]!=-1))mMx[x-1][y+1]++;
                if((x>=0)&&(x<tywwidth)&&(y-1>=0)&&(y-1<tywlength)&&(mMx[x][y-1]!=-1))mMx[x][y-1]++;
                if((x>=0)&&(x<tywwidth)&&(y+1>=0)&&(y+1<tywlength)&&(mMx[x][y+1]!=-1))mMx[x][y+1]++;
                if((x+1>=0)&&(x+1<tywwidth)&&(y-1>=0)&&(y-1<tywlength)&&(mMx[x+1][y-1]!=-1))mMx[x+1][y-1]++;
                if((x+1>=0)&&(x+1<tywwidth)&&(y>=0)&&(y<tywlength)&&(mMx[x+1][y]!=-1))mMx[x+1][y]++;
                if((x+1>=0)&&(x+1<tywwidth)&&(y+1>=0)&&(y+1<tywlength)&&(mMx[x+1][y+1]!=-1))mMx[x+1][y+1]++;
            }
        }
    }
    void tywmodel::tywclear()//清除与重置,为了再次重开使用。
    {
        mMx.clear();
    }
    void tywmodel::tywreset()
    {
        for(int i= 0;i<tywwidth;i++)
        {
            mMx.push_back(mrow(tywlength));
            for(int j=0;j<tywlength;j++)
            {
                mMx[i][j] = 0;
            }
        }
        srand(time(NULL));
        for(int i=0;i<tywtrap;)
        {
            int x = rand()%tywwidth;
            int y = rand()%tywlength;
            if(mMx[x][y]!=-1)
            {
                i++;mMx[x][y]=-1;
                if((x-1>=0)&&(x-1<tywwidth)&&(y-1>=0)&&(y-1<tywlength)&&(mMx[x-1][y-1]!=-1))mMx[x-1][y-1]++;
                if((x-1>=0)&&(x-1<tywwidth)&&(y>=0)&&(y<tywlength)&&(mMx[x-1][y]!=-1))mMx[x-1][y]++;
                if((x-1>=0)&&(x-1<tywwidth)&&(y+1>=0)&&(y+1<tywlength)&&(mMx[x-1][y+1]!=-1))mMx[x-1][y+1]++;
                if((x>=0)&&(x<tywwidth)&&(y-1>=0)&&(y-1<tywlength)&&(mMx[x][y-1]!=-1))mMx[x][y-1]++;
                if((x>=0)&&(x<tywwidth)&&(y+1>=0)&&(y+1<tywlength)&&(mMx[x][y+1]!=-1))mMx[x][y+1]++;
                if((x+1>=0)&&(x+1<tywwidth)&&(y-1>=0)&&(y-1<tywlength)&&(mMx[x+1][y-1]!=-1))mMx[x+1][y-1]++;
                if((x+1>=0)&&(x+1<tywwidth)&&(y>=0)&&(y<tywlength)&&(mMx[x+1][y]!=-1))mMx[x+1][y]++;
                if((x+1>=0)&&(x+1<tywwidth)&&(y+1>=0)&&(y+1<tywlength)&&(mMx[x+1][y+1]!=-1))mMx[x+1][y+1]++;
            }
        }
    }
    
    

    还有两个窗口界面,相应的控件需自行拖入,给个截图。

    1.png 2.png

    看似简简单单的游戏还需要这么多东西。这期间遇到了不少bug,前面的路还有很长。

    相关文章

      网友评论

      本文标题:qt制作扫雷

      本文链接:https://www.haomeiwen.com/subject/aklmvttx.html