**
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();
}