qt制作扫雷

沉默了一周我终于复活了,这回给大家带来的是扫雷。先说明一下,这个扫雷是我在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,前面的路还有很长。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容