使用Qt和C++设计“2048”游戏

**

研究git时候的无心之作。简单粗暴凑合能看,仅供消遣。

0.设计思路
0.1 建立一个主窗体,划分为4X4一共16个部分,目的是为了让每一个部分独立显示数值。
0.2 建立16个子widget,每个widget加一个label用于显示数字,同时建立一个4X4的结构体数组存储widget的坐标、值和状态
0.3 根据键盘上下左右的事件,在没有数的widget上任选两个生成随机数,默认为2或者4,并且进行运算
0.4 根据运算结果,动态的显示或者隐藏widget。
**
1.窗体

#ifndef MAINWIDGET_H
#define MAINWIDGET_H

#include 
#include 
#include 

#include "showpoint.h"

const int MAX_SIZE = 4;
typedef struct
{
    QPoint point;
    bool istrue;
    int value;
}POINT_DATA;

class MainWidget : public QWidget
{
    Q_OBJECT
public:
    MainWidget(QWidget *parent = 0);

private:
    // 初始化界面,设置窗体大小
    void init();
    void setConfig();
    // 生成随机数
    void setRandomData();
    void paintEvent(QPaintEvent *p);
    void handleKeyPressed(QKeyEvent *event);
    void moveToLeft();
    void moveToRight();
    void moveToDown();
    void moveToUp();

protected:
    bool eventFilter(QObject *object, QEvent *event);
    
private:
    POINT_DATA m_pointdata[MAX_SIZE][MAX_SIZE];
    ShowPoint *m_showPoint[MAX_SIZE][MAX_SIZE];
    QPushButton m_btnEnter;
};
#endif // MAINWIDGET_H

2. 窗体的实现

#include 
#include 
#include "mainwidget.h"

MainWidget::MainWidget(QWidget *parent)
    : QWidget(parent)
{
    init();
    setConfig();

    setRandomData();
    this->installEventFilter(this);
}

void MainWidget::init()
{
    resize(400,400);
}

void MainWidget::setConfig()
{
    for (int i = 0; i < MAX_SIZE; i++)
    {
        for (int j = 0; j < MAX_SIZE; j++)
        {
            m_pointdata[i][j].istrue = false;
            m_pointdata[i][j].point = QPoint(i * 100 , j * 100);
            m_pointdata[i][j].value = 0;
            m_showPoint[i][j] = new ShowPoint(this);
            m_showPoint[i][j]->move(i * 100, j * 100);
            m_showPoint[i][j]->setVisible(false);
        }
    }
}

void MainWidget::setRandomData()
{
    QPoint p;
    // 判断当前坐标是否已被使用
    for (int h = 0; ; h++)
    {
        if (h > 1000)
        {
            break;
        }
        bool isUsed = false;
        p.setX((qrand() % 4) * 100);
        p.setY((qrand() % 4) * 100);
        for (int i = 0; i < MAX_SIZE; i++)
        {
            for (int j = 0; j < MAX_SIZE; j++)
            {

                if (m_pointdata[i][j].istrue)
                {
                    if (m_pointdata[i][j].point.x() == p.x() && m_pointdata[i][j].point.y() == p.y())
                    {
                        isUsed = true;
                    }
                    continue;
                }
            }
        }
        if (!isUsed)
        {
            break;
        }
    }
    
    int x = p.x() / 100;
    int y = p.y() / 100;
    if((qrand() % 2) == 0)
    {
        m_pointdata[x][y].value = 2;
    }
    else
    {
        m_pointdata[x][y].value = 4;
    }
    m_pointdata[x][y].istrue = true;
    m_pointdata[x][y].point = p;
    m_showPoint[x][y]->setText(m_pointdata[x][y].value);
    m_showPoint[x][y]->show();
    return;
}

void MainWidget::paintEvent(QPaintEvent *p)
{
    QPainter painter(this);
    painter.setPen(QPen(Qt::blue));
    painter.setRenderHint(QPainter::Antialiasing, true);
    for (int i = 0; i < MAX_SIZE; i++)
    {
        painter.drawLine(0, i * 100, 400, i * 100);
        painter.drawLine(i * 100, 0, i * 100, 400);
    }
}

void MainWidget::handleKeyPressed(QKeyEvent *event)
{
    switch (event->key())
    {
        case Qt::Key_Left:
            moveToLeft();
        break;
        case Qt::Key_Up:
            moveToUp();
            break;
        case Qt::Key_Right:
            moveToRight();
            break;
        case Qt::Key_Down:
            moveToDown();
            break;
        default:
            break;
    }

    for (int i = 0; i < MAX_SIZE; i++)
    {
        for (int j = 0; j < MAX_SIZE; j++)
        {
            m_showPoint[i][j]->setVisible(false);
            if (m_pointdata[i][j].istrue)
            {
                m_showPoint[i][j]->setText(m_pointdata[i][j].value);
                m_showPoint[i][j]->move(m_pointdata[i][j].point);
                m_showPoint[i][j]->setVisible(true);
            }
        }
    }

    setRandomData();
}

void MainWidget::moveToLeft()
{
    for (int j = 0; j < MAX_SIZE; j++)
    {
        for (int i = 0; i < MAX_SIZE - 1; i++)
        {
            // 排序
            for (int p1 = 0; p1 < MAX_SIZE; p1++)
            {   // 记录循环数量,最多移动三次
                for (int p2 = 0; p2 < MAX_SIZE - 1; p2++)
                {
                    if (!m_pointdata[p2][j].istrue && m_pointdata[p2 + 1][j].istrue)
                    {
                        m_pointdata[p2][j].istrue = m_pointdata[p2 + 1][j].istrue;
                        m_pointdata[p2][j].value = m_pointdata[p2 + 1][j].value;

                        m_pointdata[p2 + 1][j].istrue = false;
                        m_pointdata[p2 + 1][j].value = 0;
                    }
                }
            }

            // 从左到右,当存在相等时,左边的数值翻倍。右边的数值为0,此时依次赋值
            if (m_pointdata[i][j].value == m_pointdata[i + 1][j].value && m_pointdata[i][j].istrue)
            {
                m_pointdata[i][j].value = m_pointdata[i][j].value * 2;
                m_pointdata[i][j].istrue = true;

                m_pointdata[i + 1][j].value = 0;
                m_pointdata[i + 1][j].istrue = false;
            }
        }
    }
}

void MainWidget::moveToRight()
{
    for (int j = 0; j < MAX_SIZE; j++)
    {
        for (int i = MAX_SIZE - 1; i > 0; i--)
        {
            // 排序
            for (int p1 = 0; p1 < MAX_SIZE; p1++)
            {   // 记录循环数量,最多移动三次
                for (int p2 = MAX_SIZE - 1; p2 > 0; p2--)
                {
                    if (!m_pointdata[p2][j].istrue && m_pointdata[p2 - 1][j].istrue)
                    {
                        m_pointdata[p2][j].istrue = m_pointdata[p2 - 1][j].istrue;
                        m_pointdata[p2][j].value = m_pointdata[p2 - 1][j].value;

                        m_pointdata[p2 - 1][j].istrue = false;
                        m_pointdata[p2 - 1][j].value = 0;
                    }
                }
            }

            // 从左到右,当存在相等时,左边的数值翻倍。右边的数值为0,此时依次赋值
            if (m_pointdata[i][j].value == m_pointdata[i - 1][j].value && m_pointdata[i][j].istrue)
            {
                m_pointdata[i][j].value = m_pointdata[i][j].value * 2;
                m_pointdata[i][j].istrue = true;

                m_pointdata[i - 1][j].value = 0;
                m_pointdata[i - 1][j].istrue = false;
            }
        }
    }
}

void MainWidget::moveToDown()
{
    for (int i = 0; i < MAX_SIZE; i++)
    {
        for (int j = MAX_SIZE - 1; j > 0; j--)
        {
            // 排序
            for (int p1 = 0; p1 < MAX_SIZE; p1++)
            {   // 记录循环数量,最多移动三次
                for (int p2 = 0; p2 < MAX_SIZE - 1; p2++)
                {
                    if (m_pointdata[i][p2].istrue && !m_pointdata[i][p2 + 1].istrue)
                    {
                        m_pointdata[i][p2 + 1].istrue = m_pointdata[i][p2].istrue;
                        m_pointdata[i][p2 + 1].value = m_pointdata[i][p2].value;

                        m_pointdata[i][p2].istrue = false;
                        m_pointdata[i][p2].value = 0;
                    }
                }
            }

            // 从左到右,当存在相等时,左边的数值翻倍。右边的数值为0,此时依次赋值
            if (m_pointdata[i][j].value == m_pointdata[i][j - 1].value && m_pointdata[i][j].istrue)
            {
                m_pointdata[i][j].value = m_pointdata[i][j].value * 2;
                m_pointdata[i][j].istrue = true;

                m_pointdata[i][j - 1].value = 0;
                m_pointdata[i][j - 1].istrue = false;
            }
        }
    }

}

void MainWidget::moveToUp()
{
    for (int i = 0; i < MAX_SIZE; i++)
    {
        for (int j = 0; j < MAX_SIZE - 1; j++)
        {
            // 排序
            for (int p1 = 0; p1 < MAX_SIZE; p1++)
            {   // 记录循环数量,最多移动三次
                for (int p2 = 0; p2 < MAX_SIZE - 1; p2++)
                {
                    if (!m_pointdata[i][p2].istrue && m_pointdata[i][p2 + 1].istrue)
                    {
                        m_pointdata[i][p2].istrue = m_pointdata[i][p2 + 1].istrue;
                        m_pointdata[i][p2].value = m_pointdata[i][p2 + 1].value;

                        m_pointdata[i][p2 + 1].istrue = false;
                        m_pointdata[i][p2 + 1].value = 0;
                    }
                }
            }

            // 从左到右,当存在相等时,左边的数值翻倍。右边的数值为0,此时依次赋值
            if (m_pointdata[i][j].value == m_pointdata[i][j + 1].value && m_pointdata[i][j].istrue)
            {
                m_pointdata[i][j].value = m_pointdata[i][j].value * 2;
                m_pointdata[i][j].istrue = true;

                m_pointdata[i][j + 1].value = 0;
                m_pointdata[i][j + 1].istrue = false;
            }
        }
    }
}

bool MainWidget::eventFilter(QObject *object, QEvent *event)
{
    if (event->type() == QEvent::KeyPress)
    {
        handleKeyPressed((QKeyEvent *)event);
        return true;
    }
    else
    {
        return QObject::eventFilter(object, event);
    }
}

3.子widget的创建

#ifndef SHOWPOINT_H
#define SHOWPOINT_H
#include 
#include 
#include 
#include 
#include 
#include 

class ShowPoint : public QWidget
{
    Q_OBJECT
public:
   ShowPoint(QWidget *parent = 0);
   
public:
   void setText(const int &text);
   int getText();

private:
    void paintEvent(QPaintEvent *p);

private:
    QLabel *m_showLabel;
};

#endif // SHOWPOINT_H

4.子widget的实现

#include "showpoint.h"
ShowPoint::ShowPoint(QWidget *parent)
          : QWidget(parent)
          , m_showLabel(new QLabel(this))
{
    resize(100,100);
    QHBoxLayout *layout = new QHBoxLayout;
    layout->addWidget(m_showLabel);
    layout->setAlignment(m_showLabel, Qt::AlignCenter);
    setLayout(layout);
}

void ShowPoint::paintEvent(QPaintEvent *p)
{
    QPainter painter(this);
    painter.setBrush(QBrush(Qt::yellow));
    painter.drawRect(0, 0, 100, 100);
}

void ShowPoint::setText(const int &text)
{
    m_showLabel->setText(QString::number(text));
}

int ShowPoint::getText()
{
    return m_showLabel->text().toInt();
}

5.主函数

#include 
#include "mainwidget.h"
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWidget mainwidget;
    mainwidget.show();
    return a.exec();
}

你可能感兴趣的:(C++,Qt,窗体)