Qt小游戏之数字华容道(百行代码搭雏形,可玩;含源码+注释)

文章目录

  • 一、数字华容道,样图如下
  • 二、废话少说直接上代码
    • 1、首先是代码文件分析
    • 2、CLabel的源码
    • 3、CMainWindow的源码
    • 4、main文件
  • 总结

一、数字华容道,样图如下

相信大家都知道华容道吧,数字华容道与其类似,源码在本文第二节(源码含详细注释)
该游戏初始化如下所示:
Qt小游戏之数字华容道(百行代码搭雏形,可玩;含源码+注释)_第1张图片
下图为游戏通关的样图:
Qt小游戏之数字华容道(百行代码搭雏形,可玩;含源码+注释)_第2张图片
提示:不会使用Qt设计师设计界面的小伙伴点击这里。

二、废话少说直接上代码

1、首先是代码文件分析

我的项目中包含内容如下所示:
Qt小游戏之数字华容道(百行代码搭雏形,可玩;含源码+注释)_第3张图片
其中CLabel.h、CLabel.cpp为继承QLabel的自定义类(在我的代码中使用的是Label作为文本显示的容器,因Label没有点击事件所以需要继承QLabel类自定义点击信号);然后CMainWindow.h、CMainWindow.cpp为调用CLabel的文件(具体看实现代码);ui文件中没有东西;main文件中则是调用CMainWindow的内容了。

2、CLabel的源码

CLabel.h文件

#ifndef CLABEL_H
#define CLABEL_H

#include 
#include 
#include 

class CLabel : public QLabel
{
    Q_OBJECT
public:
    explicit CLabel(QLabel *parent = nullptr);

    void mouseReleaseEvent(QMouseEvent *event);

signals:
    //添加点击信号
    void clicked();

public slots:
};

#endif // CLABEL_H

CLabel.cpp文件

#include "CLabel.h"

CLabel::CLabel(QLabel *parent) : QLabel(parent)
{
    //设置label对象初始化文本居中和背景颜色为白色
    this->setAlignment(Qt::AlignCenter);
    this->setStyleSheet("background-color: white");
}

void CLabel::mouseReleaseEvent(QMouseEvent *event)
{
    Q_UNUSED(event);
    emit clicked();
}

3、CMainWindow的源码

CMainWindow.h文件

#ifndef CMAINWINDOW_H
#define CMAINWINDOW_H

#include 
#include "CLabel.h"
#include 

namespace Ui {
class CMainWindow;
}
class CMainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit CMainWindow(QWidget *parent = 0);
    ~CMainWindow();
	//初始化函数
    void initial();
	//反初始化函数
    void unInitial();

private:
    Ui::CMainWindow *	ui;
    CLabel *            m_curNullLab;       //当前空值标签
    CLabel *            m_curClickLab;      //当前点击标签
    QVector<CLabel *>   m_unuseLabVector;   //当前还未使用的标签容器
    QGridLayout *       m_layout;           //网格布局器

public slots:
    //标签值更新槽函数
    void labelUpdate();
};
#endif // CMAINWINDOW_H

CMainWindow.cpp文件

#include "CMainWindow.h"
#include "ui_CMainWindow.h"
#include 
//此处的宏定义代表当前标签的行列,如当前为4,则ui有 4*4 个标签
#define MAX 4

CMainWindow::CMainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(nullptr)
    , m_layout(nullptr)
{}

CMainWindow::~CMainWindow() {}

void CMainWindow::initial()
{
    if(nullptr == ui) {
        ui = new Ui::CMainWindow;
        ui->setupUi(this);
        //网格布局器指针
        m_layout = new QGridLayout;
        //new一个label为保留位置,并连接信号槽
        m_curNullLab = new CLabel;
        connect(m_curNullLab, &CLabel::clicked, this, &CMainWindow::labelUpdate);

        int range = MAX * MAX;
        for(int index = 1; index != range; ++index) {
            //循环创建label,并设置其文本和连接信号槽
            CLabel *curLab = new CLabel;
            curLab->setText(QString::number(index));
            connect(curLab, &CLabel::clicked, this, &CMainWindow::labelUpdate);
            //将label添加到还未使用label的数组中
            m_unuseLabVector.append(curLab);
        }

        qsrand (QTime(0, 0, 0).secsTo(QTime::currentTime()));
        for(int index = 0; index != range - 1; ++index) {
            //循环获取当前未使用label数组的大小,并使用随机数取出数组中的幸运儿,并将其添加到布局器中
            int size = m_unuseLabVector.size();
            CLabel *curLab = m_unuseLabVector.takeAt(qrand() % size);
            m_layout->addWidget(curLab, index / MAX, index % MAX);
        }
        //将保留位置添加到布局器最后一格中(右下角)
        m_layout->addWidget(m_curNullLab, MAX - 1, MAX - 1);
        //将布局器设置到ui中,并设置ui的背景颜色,使其视觉上有网格效果
        ui->centralWidget->setLayout(m_layout);
        ui->centralWidget->setStyleSheet("background-color: skyblue");
    }
}

void CMainWindow::unInitial()
{
    if(nullptr != m_layout) {
        //循环获取布局器中的Item
        QLayoutItem *child;
        while (child = m_layout->takeAt(0)) {
            //获取Item中的widget指针,将其父类置空,并释放及置空
            QWidget *widget = child->widget();
            widget->setParent(nullptr);
            delete widget;
            widget = nullptr;
            //将Item指针释放并置空
            delete child;
            child = nullptr;
        }
        delete m_layout;
        m_layout = nullptr;
    }

    if(nullptr != ui) {
        delete ui;
        ui = nullptr;
    }
}

void CMainWindow::labelUpdate()
{
    //获取信号发送者的指针对象
    m_curClickLab = dynamic_cast<CLabel *>(sender());
    QString text = m_curClickLab->text();
    //获取对应控件在布局器中的位置,方便判断
    int clickIndex = m_layout->indexOf(m_curClickLab);
    int nullIndex = m_layout->indexOf(m_curNullLab);
    //当前点击label与空label位置不同且其与空label相邻时更新标签值
    if(clickIndex != nullIndex && (clickIndex + MAX == nullIndex || clickIndex - MAX == nullIndex
                                  || clickIndex + 1 == nullIndex || clickIndex - 1 == nullIndex))
    {
        //更新标签值,并将空标签指针设置为当前点击的标签
        m_curClickLab->setText("");
        m_curNullLab->setText(text);
        m_curNullLab = m_curClickLab;
    }
}

4、main文件

main.cpp

#include "CMainWindow.h"
#include 

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    CMainWindow w;
    w.initial();
    w.show();
    int exec = a.exec();
    w.unInitial();
    return exec;
}

总结

我的代码能完成字符移动了,功能还差一些,如:重新开始、更改游戏难度、游戏胜利等,这些功能依旧容易实现,我就不做了,哈哈哈
本文为超简单小游戏,对新手可能会有用一些,其余就没什么可说的了

友情提示——哪里看不懂可私哦,让我们一起互相进步吧
(创作不易,请留下一个免费的赞叭 谢谢 ^o^/)

注:文章为作者编程过程中所遇到的问题和总结,内容仅供参考,若有错误欢迎指出。
注:如有侵权,请联系作者删除

你可能感兴趣的:(Qt,qt,开发语言)