QT扫雷小结

作者: Seven禅那 | 来源:发表于2017-02-08 12:39 被阅读326次

扫雷的游戏规则

首先简单的说一下扫雷的游戏规则,是一款9宫格类型的鼠标点击游戏。
点击到地雷,即游戏结束。
标识完全部的地雷,或者将除了地雷以外的地图全部打开即完成游戏的胜利。
每个地雷周围的8个格子都会显示相应数量的地雷数。因此可以判定该格子周边有多少个地雷,依据这个提示信息进行排查。

扫雷游戏实现

布图总的来说是基于9宫格类型来实现的,即按照X,Y坐标轴进行布图。
游戏规则则是通过二维显示层与二维显示层所对应的逻辑层,通过鼠标点击事件衔接在一起实现。
即C++的两个变长数组相套用。vector中再放置一个vector。
因为是相对应,所以单个显示的框框是两个变长数组的vector;
逻辑判断层也是两个变长数组的vector;

扫雷.png

QT界面层

基于VSI框架

QGraphicsView容器类

在这个界面容器类中可以放置QGraphicsScene场景类

QGraphicsScene场景类

在这个场景类中可以放置QGraphicsItem图元类,即单个显示的雷框

QGraphicsItem图元类

在这个图元类中可以支持贴图和鼠标点击事件,点击事件对应的坐标图元和图元对应逻辑的响应,实现扫雷的游戏

逻辑处理层

前面已经提到时两个变长的二维数组相对应实现。
二维数组xxx[X][Y]相应地址的值与QGraphicsItem的单个坐标图元相对应。

由于场景显示中共有10种情况,即雷,空白格,和数字1~8;
所以可以通过给二维变长数组的赋不同值进行区别;
判断不同的值显示不同的图片;

QT代码实现

界面生成

mian函数

重点在于要定义一个全局的mainwindow的对象,方便其他类调用

#include "mainwindow.h"
#include "myscene.h"
#include <QApplication>
#include "model.h"

int width1=8; //单元长度
int height1=8;//单元高度
int boomNum=5;//起始地雷数
int showBoom=boomNum;//显示地雷数字
int flag=0;//标识
int go_flag=0;//游戏结束标识
int time_num;//运行时间
int win_game=width1*height1-boomNum;//游戏胜利条件
model m; //图元类对象
MainWindow *w;//主要窗口指针,方便调用
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow p;
    w=&p; //指针指向分配空间的窗口对象
    w->show();
    return a.exec(); //阻塞显示
}

mianwindow类

重点在于那个自适应的边框设定,以后要拉出来,方便自定义游戏的宽度和高度

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->graphicsView->setScene(&sc); //设置界面

    sc.setSceneRect(sc.itemsBoundingRect());
    ui->graphicsView->setFixedSize(sc.sceneRect().width() +5,sc.sceneRect().height()+5);//设置单个图元间距
    this->resize(ui->graphicsView->width(),ui->graphicsView->height()+ 105);//设置场景边框大小

    ui->label_time->setText("0"); //显示默认时间
    QString temp = QString::number(boomNum,10);
    ui->label_boom->setText(temp);//显示雷数
    time_num=0;
    p=new QTimer;  //计时器
    connect(p,SIGNAL(timeout()),this,SLOT(settime())); //连接计时信号函数
}

QGraphicsScene类

构建场景
固定的格式,将图元添加进场景中;
重点要新建一个二维变长的vector

#ifndef MYSCENE_H
#define MYSCENE_H
#include "myitem.h"
#include <QGraphicsScene>
#include <vector>
using namespace std;
typedef vector<myitem*> irow;
typedef vector<irow> imap;  //变长的二维vector
class myscene : public QGraphicsScene
{
    Q_OBJECT
public:
    explicit myscene(QObject *parent = 0);
    static int Long,Width;
    void removeAlliMx();
    void resetAlliMx();
    imap iMx;
signals:

public slots:
};

#endif // MYSCENE_H
myscene::myscene(QObject *parent) : QGraphicsScene(parent)
{
    for(int i=0;i<width1;i++)
    {
        iMx.push_back(irow(height1));
        for(int j=0;j<height1;j++)
        {
            iMx[i][j] = new myitem(i,j);
            //添加进场景
            addItem(iMx[i][j]);
            //设置图元位置
            iMx[i][j]->setPos(iMx[i][j]->boundingRect().width()*j,iMx[i][j]->boundingRect().height()*i); //坐标构建   iMx对象
        }
    }
}

QGraphicsPixmapItem类

整个游戏的难点应该在这个类里面
要写一个相应图元的递归函数

#include "myitem.h"
#include <QPixmap>
#include "myscene.h"
#include <QGraphicsScene>
#include <vector>
#include <QDebug>
#include <QGraphicsSceneMouseEvent>
#include "model.h"
#include "dialog_gameover.h"
#include "dialog_wingame.h"
#include "mainwindow.h"
extern model m;
extern int flag;
extern int width1;
extern int height1;
extern int go_flag;
extern int win_game;
extern int boomNum;
extern int showBoom;
extern MainWindow *w;
//初始每个图元的显示
myitem::myitem(int x,int y)
{
    QPixmap t(":/1.jpg");
    t = t.scaled(60,60);
    setPixmap(t);
    m_x = x;m_y = y;
    rightClick=0;
    m_flag=0;
}

void myitem::mousePressEvent(QGraphicsSceneMouseEvent * event)//鼠标点击事件虚函数
{
    ((myscene*)scene())->iMx;
    if(event->button()==Qt::LeftButton)//分辨左点击和右点击
    {
        w->run(); //计时器运行
        showItem(); //调用显示函数
    }
    if(event->button()==Qt::RightButton) //右击事件
    {
        if(0==rightClick) //右击单次
        {
            QPixmap t(":/3.jpg");
            t = t.scaled(60,60);
            setPixmap(t);
            rightClick=1;
            if(showBoom>0)//地雷显示数
            showBoom--;
            w->showboomNum();
        }
        else if(1==rightClick)//右击双次
        {
            QPixmap t(":/1.jpg");
            t = t.scaled(60,60);
            setPixmap(t);
            rightClick=0;
            if(showBoom>=0&&showBoom<boomNum)//地雷显示数
            showBoom++;
            w->showboomNum();
        }
    }
}

void myitem::showItem()
{
    if(m_flag)return;
    m_flag=1;
    switch (m.mMx[m_x][m_y]) //匹配二维变长容器,并显示对应图片
    {
    case 0:
    {
        QPixmap t(":/4.jpg");  //导入资源文件
        t = t.scaled(60,60);//设置界面大小
        setPixmap(t);  //显示文件
        win_game--;
        break;
    }
    case -1:
    {
        QPixmap t(":/2.jpg");
        t = t.scaled(60,60);//设置界面大小
        setPixmap(t);
        win_game+=1000;
        showAllItem(); //点击雷则游戏结束,打开全局场景
        break;
    }
    case 1:
    {
        QPixmap t(":/01.jpg");
        t = t.scaled(60,60);//设置界面大小
        setPixmap(t);
        win_game--;
        break;
    }
    case 2:
    {
        QPixmap t(":/02.jpg");
        t = t.scaled(60,60);//设置界面大小
        setPixmap(t);
        win_game--;
        break;
    }
    case 3:
    {
        QPixmap t(":/03.jpg");
        t = t.scaled(60,60);//设置界面大小
        setPixmap(t);
        win_game--;
        break;
    }
    case 4:
    {
        QPixmap t(":/04.jpg");
        t = t.scaled(60,60);//设置界面大小
        setPixmap(t);
        win_game--;
        break;
    }
    case 5:
    {
        QPixmap t(":/05.jpg");
        t = t.scaled(60,60);//设置界面大小
        setPixmap(t);
        win_game--;
        break;
    }
    case 6:
    {
        QPixmap t(":/06.jpg");
        t = t.scaled(60,60);//设置界面大小
        setPixmap(t);
        win_game--;
        break;
    }
    case 7:
    {
        QPixmap t(":/07.jpg");
        t = t.scaled(60,60);//设置界面大小
        setPixmap(t);
        win_game--;
        break;
    }
    case 8:
    {
        QPixmap t(":/08.jpg");
        t = t.scaled(60,60);//设置界面大小
        setPixmap(t);
        win_game--;
        break;
    }

    }

    if(m.mMx[m_x][m_y]==0) //如果是空白则递归显示
    {
        int myrow;
        int mycolumn;
        for(int i=-1;i<2;i++)
        {
            for(int 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>=width1||mycolumn>=height1)
                {
                    continue;
                }
                ((myscene*)scene())->iMx[myrow][mycolumn]->showItem(); //循环调用递归函数

            }

        }

    }
    if(0==win_game) //判断胜利
    {
        win_game+=1000;
        go_flag+=1000;
        Dialog_wingame *win = new Dialog_wingame;
        win->show();
        w->stop();
        showAllItem();
    }
}


void myitem::showAllItem()
{
    for(int i =0;i<width1;i++)
    {
        for(int j=0;j<height1;j++)
        {
            ((myscene*)scene())->iMx[i][j]->showItem();
        }
    }
    if(0 == go_flag) //判断游戏结束
    {
    Dialog_gameover *d = new Dialog_gameover;
    d->show();
    w->stop();
    go_flag++;
    }
}

基本就是这个思路完成了游戏,下面就是自已写的自定义之类的,细节完善的工作,根据自己的癖好修饰修饰;

相关文章

  • QT扫雷小结

    扫雷的游戏规则 首先简单的说一下扫雷的游戏规则,是一款9宫格类型的鼠标点击游戏。点击到地雷,即游戏结束。标识完全部...

  • Qt学习- (扫雷项目初学)

    Qt学习 扫雷教学 QGraphicsView的框架QGraphicsView 容器 -> QGraphics...

  • qt制作扫雷

    沉默了一周我终于复活了,这回给大家带来的是扫雷。先说明一下,这个扫雷是我在ubuntu下用c++编写,qt制作的,...

  • 小赚红包扫雷平台开发

    小赚红包扫雷系统app开发,小赚红包扫雷源码搭建,小赚社区红包扫雷,小赚扫雷系统app,提供小赚红包扫雷服务器、域...

  • Qt 的 paintEvent 函数小结

    Qt 的 paintEvent 函数小结 当产生一个绘制事件并且调用paintEvent()函数的时候,会出现如下...

  • 扫雷红包飞信扫雷系统模式现成开发

    扫雷红包飞信扫雷系统模式现成开发、虾聊扫雷系统app源码开发,樱桃红包扫雷系统app源码开发、博友红包扫雷系统ap...

  • Web版扫雷开发小记(3)

    前篇: web版扫雷开发小记(1)web版扫雷开发小记(2)web版扫雷开发小记(3)web版扫雷开发小记(4) ...

  • Web扫雷开发小记(1)

    目录Web扫雷开发小记(2)Web扫雷开发小记(3)Web扫雷开发小记(4) 刚好今天做阿里前端笔试问到扫雷了,那...

  • web版扫雷开发小记(4)

    目录:Web扫雷开发小记(1)Web扫雷开发小记(2)Web扫雷开发小记(3) 其实在完成上篇的功能之后,一个扫雷...

  • 飞信红包扫雷系统源码平台

    飞信红包扫雷系统app源码开发、腾信红包扫雷系统app源码、诚信红包扫雷系统app开发、提供红包扫雷系统服务器、域...

网友评论

    本文标题:QT扫雷小结

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