Qt浅谈之二十五2048游戏(原始代码来自网络)

来源:互联网 发布:龙江网络农垦广电 编辑:程序博客网 时间:2024/06/05 14:20

一、简介

        Qt改写2048游戏,在linux系统下找寻android的视觉效果。

二、运行图

        启动运行图:

三、详解

1、代码

(1)widget.h

#ifndef WIDGET_H#define WIDGET_H#include <QWidget>#include <QLabel>#include <QPushButton>#include <QMessageBox>#include <QFile>#include <QtGui>#include "GameWidget.h"// 主窗口部件类class Widget : public QWidget{    Q_OBJECTpublic:    // 构造&析构函数    Widget(QWidget *parent = 0);    ~Widget();private:    // “restart”按钮    QPushButton *restartBtn;    QPushButton *closeBtn;    // “score”标签    QLabel *titleLabel;    QLabel *tipsLabel;    QLabel *scoreLbl;    // “HightScore”标签    QLabel *highScoreLbl;    // 游戏部件    GameWidget *gameWidget;    // 宽度和高度的缩放比例 用来使窗口部件随主窗口的尺寸改变而改变位置与尺寸    qreal ratioW, ratioH;    // 记录最高分    int highScore;    QPoint dragPosition;    bool bPressFlag;protected:    // 窗口尺寸改变触发的事件    void resizeEvent(QResizeEvent *);    void keyPressEvent(QKeyEvent * event);    void mousePressEvent(QMouseEvent *event);    void mouseMoveEvent(QMouseEvent *event);    void mouseReleaseEvent(QMouseEvent *event);public slots:    // 处理分数增加信号的槽函数    void onScoreInc(int);    // 处理游戏结束信号的槽函数    void onGameOver();    // 处理游戏获胜信号的槽函数    void onWin();};#endif // WIDGET_H
(2)widget.cpp
#include "widget.h"Widget::Widget(QWidget *parent)    : QWidget(parent, Qt::FramelessWindowHint)    , bPressFlag(false){    setAutoFillBackground(true);    QPalette pal = palette();    pal.setColor(QPalette::Background, QColor("#FAF8F0"));    setPalette(pal);    titleLabel = new QLabel(tr("2048"), this);    titleLabel->setStyleSheet("color:#746D65;");    titleLabel->setFont(QFont("arial", 45, QFont::Black));    tipsLabel = new QLabel(tr("Join the numbers and get to the 2048 tile!"), this);    tipsLabel->setStyleSheet("color:#B3AFA7;");    tipsLabel->setFont(QFont("arial", 10, QFont::Normal));    // 初始化最高分为0    highScore = 0;    // 读取存储最高分的文件    QFile file("score.j");    if (file.open(QIODevice::ReadOnly))    {        file.read((char *)&highScore, sizeof(highScore));        file.close();    }    // 构造一个游戏部件对象    gameWidget = new GameWidget(this);    //gameWidget->setGeometry(2, 200, 400, 400);    gameWidget->setFocus();    connect(gameWidget, SIGNAL(ScoreInc(int)), this, SLOT(onScoreInc(int)));    connect(gameWidget, SIGNAL(GameOver()), this, SLOT(onGameOver()));    connect(gameWidget, SIGNAL(win()), this, SLOT(onWin()));    // 构造一个字体对象    QFont font;    font.setFamily("Arial");    font.setBold(true);    font.setPixelSize(15);    // 构造一个按钮对象    restartBtn = new QPushButton("New Game", this);    //restartBtn->setGeometry(100, 120, 200, 50);    restartBtn->setFont(font);    restartBtn->setStyleSheet("QPushButton{color: white;background:#907963;border-style:flat;}");    //restartBtn->setFlat(true);    restartBtn->setFocusPolicy(Qt::NoFocus);    connect(restartBtn, SIGNAL(clicked()), gameWidget, SLOT(restart()));    // 构造一个标签对象    highScoreLbl = new QLabel(QString("BEST\n%1").arg(highScore),this);    //highScoreLbl->setGeometry(220, 30, 150, 50);    highScoreLbl->setFont(font);    highScoreLbl->setAlignment(Qt::AlignCenter);    highScoreLbl->setStyleSheet("QLabel{color:#FFFFEE;background:#BEAD9D}");    // 构造一个标签对象    scoreLbl = new QLabel("SCORE\n0", this);    //scoreLbl->setGeometry(30, 30, 150, 50);    scoreLbl->setFont(font);    scoreLbl->setAlignment(Qt::AlignCenter);    scoreLbl->setStyleSheet("QLabel{color:#FFFFEE;background:#BEAD9D}");    closeBtn = new QPushButton("x", this);    closeBtn->setFocusPolicy(Qt::NoFocus);    closeBtn->setFont(QFont("Arial", 11, QFont::Normal));    closeBtn->setStyleSheet("QPushButton{border-style:flat;color:#BDAD9F}"                        "QPushButton:hover{border-style:flat;color:#FF0000}");    closeBtn->setCursor(Qt::PointingHandCursor);    closeBtn->setGeometry(400 - 18, 3, 15, 15);    connect(closeBtn, SIGNAL(clicked()), this, SLOT(close()));    // 重置窗口大小    resize(400, 510);    move((QApplication::desktop()->width() - width())/2,  (QApplication::desktop()->height() - height())/2);}Widget::~Widget(){    // 释放相关对象    delete restartBtn;    delete scoreLbl;    delete highScoreLbl;    delete gameWidget;}void Widget::onScoreInc(int score){    // 更新分数显示    scoreLbl->setText(QString("Score:\n %1").arg(score));    // 如果当前分数高于最高分    if (score > highScore)    {        // 更新最高分        highScore = score;        highScoreLbl->setText(QString("BEST:\n %1").arg(highScore));        // 将新的最高分存入文件        QFile file("score.j");        file.open(QIODevice::WriteOnly);        file.write((char *)&highScore, sizeof(highScore));        file.close();    }}void Widget::onGameOver(){    QMessageBox::information(this, "GameOver", "You lost !");}void Widget::onWin(){    QMessageBox::information(this, "Congratulation", "You win !");}void Widget::resizeEvent(QResizeEvent *){    // 计算宽度和高度的缩放比例    ratioW = width() / 400.0f;    ratioH = height() / 510.0f;    // 重置子部件大小和位置    titleLabel->setGeometry(20 * ratioW, 40 * ratioH , 130 * ratioW, 50 * ratioH);    tipsLabel->setGeometry(20 * ratioW, 100 * ratioH , 300 * ratioW, 20 * ratioH);    gameWidget->setGeometry(18 * ratioW, 140 * ratioH, 365 * ratioW, 365 * ratioH);    restartBtn->setGeometry(280 * ratioW, 90 * ratioH, 100 * ratioW, 30 * ratioH);    highScoreLbl->setGeometry(300 * ratioW, 40 * ratioH, 80 * ratioW, 40 * ratioH);    scoreLbl->setGeometry(210 * ratioW, 40 * ratioH, 80 * ratioW, 40 * ratioH);}void Widget::keyPressEvent(QKeyEvent *event){    gameWidget->setFocus();    QWidget::keyPressEvent(event);}void Widget::mousePressEvent ( QMouseEvent * event){    bPressFlag = true;    dragPosition = event->pos();    QWidget::mousePressEvent(event);}void Widget::mouseMoveEvent(QMouseEvent *event){    if (bPressFlag) {        QPoint relaPos(QCursor::pos() - dragPosition);        move(relaPos);    }    QWidget::mouseMoveEvent(event);}void Widget::mouseReleaseEvent(QMouseEvent *event){    bPressFlag = false;    QWidget::mouseReleaseEvent(event);}
(3)GameWidget.h
#ifndef GAMEWIDGET_H#define GAMEWIDGET_H#include <QWidget>#include <QMouseEvent>#include <QEventLoop>#include <QTimer>#include <QPainter>#include <QList>// 手势的方向enum GestureDirect{    LEFT = 0,   // 向左    RIGHT = 1,  // 向右    UP = 2,     // 向上    DOWN = 3    // 向下};// 定义动画的类型enum AnimationType{    MOVE = 0,       // 方格移动动画    APPEARANCE = 1  // 方格出现动画};// 动画结构体struct Animation{    AnimationType type;     // 动画类型    GestureDirect direct;   // 方向    QPointF startPos;       // 起始点坐标 出现动画仅仅使用这个坐标    QPointF endPos;         // 终止点坐标 移动动画的终点坐标    int digit;              // 数码    int digit2;             // 第二数码 数码可能被合并};// 游戏部件类 继承自QWidgetclass GameWidget : public QWidget{    Q_OBJECTpublic:    // 构造函数    explicit GameWidget(QWidget *parent = 0);protected:    void keyPressEvent(QKeyEvent * event);private:    // 游戏面板 存储每个格子的数值    int board[4][4];    // 数码的个数 存储当前面板上的数字的个数    int digitCount;    // 分数 存储当前得分    int score;    // 起始点坐标 存储手势起点坐标    QPoint startPos;    // 存储所有需要展现的动画    QList<Animation> animationList;    // 小格子的宽度和高度    qreal w, h;    // 缓存图像    QImage *cacheImg;    // 是否在播放动画效果    bool isAnimating;    // 检测游戏是否结束    bool checkGameOver();    // 检测游戏是否获胜    bool checkWin();    /* 获取一个数字的二进制位数 当然这里获取的不完全是二进制位数 而是对应颜色数组的下标    比如 2 对应 0    8 对应 2*/    int getBitCount(int);    // 绘制动画效果    bool playAnimation(Animation&, QPainter&);    // 鼠标按下触发的事件    void mousePressEvent(QMouseEvent *);    // 鼠标释放触发的时间    void mouseReleaseEvent(QMouseEvent *);    // 绘制事件    void paintEvent(QPaintEvent *);    // 以下为一些信号signals:    // 手势移动信号    void GestureMove(GestureDirect);    // 分数增加信号    void ScoreInc(int);    // 游戏结束信号    void GameOver();    // 游戏获胜信号    void win();    // 以下为一些槽函数public slots:    // 处理手势移动信号的槽函数    void onGestureMove(GestureDirect);    // 重新开始的槽函数    void restart();};#endif // GAMEWIDGET_H
(4)GameWidget.cpp
#include <QDebug>#include "GameWidget.h"// 颜色数组 存储每个数字对应的背景色QColor digitBkg[11] = {QColor::fromRgb(0xEE, 0xE5, 0xDB), QColor::fromRgb(0xEC, 0xE0, 0xC8),                            QColor::fromRgb(0xF2, 0xAF, 0x78), QColor::fromRgb(0xEE, 0x8A, 0x54),                            QColor::fromRgb(0xFE, 0x76, 0x5E), QColor::fromRgb(0xE7, 0x58, 0xC),                            QColor::fromRgb(0xFF, 0x66, 0x66), QColor::fromRgb(0xF1, 0xCF, 0x48),                            QColor::fromRgb(0xCC, 0x33, 0x33), QColor::fromRgb(0xE3, 0xB9, 0x11),                            QColor::fromRgb(0xFF, 0x00, 0x00)};// 每个方向位置的增量QPointF dPos[5] = {QPointF(-10, 0), QPointF(10, 0), QPointF(0, -10), QPointF(0, 10), QPointF(-2, -2)};GameWidget::GameWidget(QWidget *parent) :    QWidget(parent){    // 连接手势移动信号和相应的槽函数    connect(this, SIGNAL(GestureMove(GestureDirect)), SLOT(onGestureMove(GestureDirect)));    // 初始化board数组    memset(board, 0, sizeof(board));    // 随机填入两个2    board[rand() % 4][rand() % 4] = 2;    while(true) {        int x = rand() % 4;        int y = rand() % 4;        if (board[x][y] != 0) {            continue;        }        else {            board[x][y] = 2;            break;        }    }    // 分数初始化为0    score = 0;    // 数码个数初始化为2    digitCount = 2;    isAnimating = false;    cacheImg = NULL;}void GameWidget::keyPressEvent(QKeyEvent *event){    if (isAnimating)        return;    switch (event->key()) {        case Qt::Key_Left:            emit GestureMove(LEFT);        break;        case Qt::Key_Right:            emit GestureMove(RIGHT);        break;        case Qt::Key_Down:            emit GestureMove(DOWN);        break;        case Qt::Key_Up:            emit GestureMove(UP);        break;        default:        break;    }    QWidget::keyPressEvent(event);}void GameWidget::mousePressEvent(QMouseEvent *e){    // 获取起点坐标    startPos = e->pos();}void GameWidget::mouseReleaseEvent(QMouseEvent *e){    // 如果在播放动画效果则直接退出防止重复产生手势事件    if (isAnimating)        return;    // 根据终点坐标和起点坐标计算XY坐标的增量    float dX = (float)(e->pos().x() - startPos.x());    float dY = (float)(e->pos().y() - startPos.y());    // 确定手势方向    if (abs(dX) > abs(dY))    {        if (dX < 0)            emit GestureMove(LEFT);        else            emit GestureMove(RIGHT);    }    else    {        if (dY < 0)            emit GestureMove(UP);        else            emit GestureMove(DOWN);    }}void GameWidget::onGestureMove(GestureDirect direct){    int i, j, k;    Animation a;    // 是否合并过方格    bool combine = false;    // 处理不同方向    switch (direct)    {    // 向左    case LEFT:        // 循环每一行        for (i = 0; i < 4; i++)        {            /* 初始化j k为0             * 这里j表示要交换的数字列号             * k表示交换到的位置的列号             * */            j = 0, k = 0, combine = false;            while (true)            {                // 循环找到第一个不是0的数字对应的列号                while (j < 4 && board[i][j] == 0)                    j++;                // 如果超过了3则说明搜索完毕 推出循环                if (j > 3)                    break;                // 交换两个数字                qSwap(board[i][k], board[i][j]);                // 记录动画信息                a.type = MOVE;                a.startPos = QPointF(7 + (w + 5) * j, 7 + (h + 5) * i);                a.endPos = QPointF(7 + (w + 5) * k, 7 + (h + 5) * i);                a.digit = a.digit2 = board[i][k];                a.direct = LEFT;                //如果交换后的数字与其前一列的数字相同                if (!combine && k > 0 && board[i][k] == board[i][k - 1])                {                    // 前一列的数字*2                    board[i][k - 1] <<= 1;                    // 这一列的数字置为0                    board[i][k] = 0;                    // 记录动画信息                    a.digit2 = board[i][k - 1];                    a.endPos = QPointF(7 + (w + 5) * (k - 1), 7 + (h + 5) * i);                    // 增加分数                    score += board[i][k - 1];                    // 发射增加分数的信号                    emit ScoreInc(score);                    // 数码个数-1                    digitCount--;                    combine = true;                }                else                    k++;                j++;                // 添加到动画链表                animationList.append(a);            }        }        break;        // 其余三个方向与左向类似    case RIGHT:        for (i = 0; i < 4; i++)        {            j = 3, k = 3, combine = false;            while (true)            {                while (j > -1 && board[i][j] == 0)                    j--;                if (j < 0)                    break;                qSwap(board[i][k], board[i][j]);                a.type = MOVE;                a.startPos = QPointF(7 + (w + 5) * j, 7 + (h + 5) * i);                a.endPos = QPointF(7 + (w + 5) * k, 7 + (h + 5) * i);                a.digit = a.digit2 = board[i][k];                a.direct = RIGHT;                if (!combine && k < 3 && board[i][k] == board[i][k + 1])                {                    board[i][k + 1] <<= 1;                    board[i][k] = 0;                    a.digit2 = board[i][k + 1];                    a.endPos = QPointF(7 + (w + 5) * (k + 1), 7 + (h + 5) * i);                    score += board[i][k + 1];                    emit ScoreInc(score);                    digitCount--;                    combine = true;                }                else                    k--;                j--;                animationList.append(a);            }        }        break;    case UP:        for (i = 0; i < 4; i++)        {            j = 0, k = 0, combine = false;            while (true)            {                while (j < 4 && board[j][i] == 0)                    j++;                if (j > 3)                    break;                qSwap(board[k][i], board[j][i]);                a.type = MOVE;                a.startPos = QPointF(7 + (w + 5) * i, 7 + (h + 5) * j);                a.endPos = QPointF(7 + (w + 5) * i, 7 + (h + 5) * k);                a.digit = a.digit2 = board[k][i];                a.direct = UP;                if (!combine && k > 0 && board[k][i] == board[k - 1][i])                {                    board[k - 1][i] <<= 1;                    board[k][i] = 0;                    a.digit2 = board[k - 1][i];                    a.endPos = QPointF(7 + (w + 5) * i, 7 + (h + 5) * (k - 1));                    score += board[k - 1][i];                    emit ScoreInc(score);                    digitCount--;                    combine = true;                }                else                    k++;                j++;                animationList.append(a);            }        }        break;    case DOWN:        for (i = 0; i < 4; i++)        {            j = 3, k = 3, combine = false;            while (true)            {                while (j > -1 && board[j][i] == 0)                    j--;                if (j < 0)                    break;                qSwap(board[k][i], board[j][i]);                a.type = MOVE;                a.startPos = QPointF(7 + (w + 5) * i, 7 + (h + 5) * j);                a.endPos = QPointF(7 + (w + 5) * i, 7 + (h + 5) * k);                a.digit = a.digit2 = board[k][i];                a.direct = DOWN;                if (!combine && k < 3 && board[k][i] == board[k + 1][i])                {                    board[k + 1][i] <<= 1;                    board[k][i] = 0;                    a.digit2 = board[k + 1][i];                    a.endPos = QPointF(7 + (w + 5) * i, 7 + (h + 5) * (k + 1));                    score += board[k + 1][i];                    emit ScoreInc(score);                    digitCount--;                    combine = true;                }                else                    k--;                j--;                animationList.append(a);            }        }        break;    }    bool flag_move = false;    for(int index = 0; index < animationList.size(); index++) {        if (animationList.at(index).startPos != animationList.at(index).endPos) {            flag_move = true;            break;        }    }    // 如果数字木有填满    if (digitCount != 16 && flag_move)    {        // 随机产生行号和列号        i = rand() % 4, j = rand() % 4;        // 循环直到行和列对应的元素为0        while (board[i][j] != 0)            i = rand() % 4, j = rand() % 4;        // 填入2        //board[i][j] = (rand() % 2 + 1) * 2;        board[i][j] = 2;        // 记录动画信息        a.type = APPEARANCE;        a.startPos = a.endPos = QPointF(7 + (w + 5) * j, 7 + (h + 5) * i);        a.startPos += QPointF(w / 2, h / 2);        a.digit = board[i][j];        // 数码个数加一        digitCount++;    }    else    {        // 如果数字填满了 检测游戏是否over        if (checkGameOver())            emit GameOver();// 如果游戏over了则发射GameOver信号    }    // 开始绘制动画效果    isAnimating = true;    // 动画列表的迭代器    QList<Animation>::iterator it;    // 事件循环 用于延时    QEventLoop eventLoop;    // 删除之前的缓存图像    if (cacheImg)        delete cacheImg;    // 建立缓存图像    cacheImg = new QImage(width(), height(), QImage::Format_ARGB32);    // 清空图像    cacheImg->fill(0);    // 构造一个QPainter对象    QPainter painter(cacheImg);    // 字体    QFont font;    font.setFamily("Consolas");    font.setBold(true);    font.setPixelSize(40);    painter.setFont(font);    // 标识所有方格动画是否都播放完毕    bool ok = false;    while (true)    {        // 构造一个画刷 颜色为R G B分量分别为141 121 81的颜色        QBrush brush(QColor::fromRgb(141, 121, 81));        // 使painter应用这个画刷        painter.setBrush(brush);        // 设置画笔为空笔 目的是使绘制的图形没有描边        painter.setPen(Qt::NoPen);        // 绘制一个矩形        painter.drawRect(2, 2, width() - 4, height() - 4);        // 设置画刷颜色为 RGB分量为171 165 141的颜色        brush.setColor(QColor::fromRgb(171, 165, 141));        // 应用这个画刷        painter.setBrush(brush);        // 循环绘制游戏面板        for (int i = 0; i < 4; i++)            for (int j = 0; j < 4; j++)                // 绘制小方格                painter.drawRect(QRectF(7 + (w + 5) * j, 7 + (h + 5) * i, w, h));        // 假设都播放完毕        ok = true;        // 循环播放每个方格动画        for (it = animationList.begin(); it != animationList.end(); it++)            if (!playAnimation(*it, painter))                ok = false;        // 刷新部件        update();        // 全部播放完则退出        if (ok)            break;        // 延时5ms        QTimer::singleShot(5, &eventLoop, SLOT(quit()));        eventLoop.exec();    }    // 播放方格出现的动画    while (!playAnimation(a, painter))    {        update();        QTimer::singleShot(5, &eventLoop, SLOT(quit()));        eventLoop.exec();    }    //清除所有动画    animationList.clear();    //刷新当前部件    isAnimating = false;    // 检测游戏是否获胜    if (checkWin())        emit win();// 如果获胜则发射win信号    update();}bool GameWidget::playAnimation(Animation& a, QPainter& painter){    bool rtn = false;    QBrush brush(Qt::SolidPattern);    // 移动方格位置    if (a.type == MOVE)    {        switch (a.direct)        {        case LEFT:            if (a.startPos.x() > a.endPos.x())                a.startPos += dPos[LEFT];            else                a.startPos = a.endPos, rtn = true;            break;        case RIGHT:            if (a.startPos.x() < a.endPos.x())                a.startPos += dPos[RIGHT];            else                a.startPos = a.endPos, rtn = true;            break;        case UP:            if (a.startPos.y() > a.endPos.y())                a.startPos += dPos[UP];            else                a.startPos = a.endPos, rtn = true;            break;        case DOWN:            if (a.startPos.y() < a.endPos.y())                a.startPos += dPos[DOWN];            else                a.startPos = a.endPos, rtn = true;        }        // 如果方格移动到终点        if (!rtn)        {            brush.setColor(digitBkg[getBitCount(a.digit)]);            painter.setBrush(brush);            painter.drawRect(QRectF(a.startPos.x(), a.startPos.y(), w, h));            painter.setPen(QColor::fromRgb(0, 0, 0));            painter.drawText(QRectF(a.startPos.x(), a.startPos.y(), w, h), Qt::AlignCenter,                             QString::number(a.digit));        }        else        {            brush.setColor(digitBkg[getBitCount(a.digit2)]);            painter.setBrush(brush);            painter.drawRect(QRectF(a.startPos.x(), a.startPos.y(), w, h));            painter.setPen(QColor::fromRgb(0, 0, 0));            painter.drawText(QRectF(a.startPos.x(), a.startPos.y(), w, h), Qt::AlignCenter,                             QString::number(a.digit2));        }        painter.setPen(Qt::NoPen);    }    else    {        // 方格出现的动画效果        if (a.startPos.x() > a.endPos.x())            a.startPos += dPos[4];        else            a.startPos = a.endPos, rtn = true;        brush.setColor(digitBkg[getBitCount(a.digit)]);        painter.setBrush(brush);        painter.drawRect(QRectF(a.startPos.x(), a.startPos.y(),                         w - 2 * (a.startPos.x() - a.endPos.x()),                         h - 2 * (a.startPos.y() - a.endPos.y())));        painter.setPen(QColor::fromRgb(0, 0, 0));        painter.drawText(QRectF(a.endPos.x(), a.endPos.y(), w, h),                         Qt::AlignCenter, QString::number(a.digit));        painter.setPen(Qt::NoPen);    }    return rtn;}void GameWidget::paintEvent(QPaintEvent *){    // 构造一个QPainter对象 使用它来进行绘图    QPainter painter(this);    // 如果正在播放动画效果则绘制缓存位图    if (isAnimating)    {        painter.drawImage(0, 0, *cacheImg);        return;    }    // 构造一个画刷 颜色为R G B分量分别为141 121 81的颜色    QBrush brush(QColor::fromRgb(141, 121, 81));    // 使painter应用这个画刷    painter.setBrush(brush);    // 设置画笔为空笔 目的是使绘制的图形没有描边    painter.setPen(Qt::NoPen);    // 绘制一个矩形    painter.drawRect(2, 2, width() - 4, height() - 4);    // 计算每个小格子的宽度和高度    w = width() - 4, h = height() - 4;    w = (w - 25) / 4, h = (h - 25) / 4;    /* 构造一个字体     * 字体名字为Consolas     * 字体设置为粗体     * 字体大小为40像素     * */    QFont font;    font.setFamily("Consolas");    font.setBold(true);    font.setPixelSize(40);    // 使painter应用这个字体    painter.setFont(font);    // 循环绘制游戏面板    for (int i = 0; i < 4; i++)        for (int j = 0; j < 4; j++)        {            // 如果方格中有数字            if (board[i][j])            {                // 设置画刷颜色为数码对应的颜色                brush.setColor(digitBkg[getBitCount(board[i][j])]);                // 应用这个画刷                painter.setBrush(brush);                // 绘制一个小方格                painter.drawRect(QRectF(7 + (w + 5) * j, 7 + (h + 5) * i, w, h));                // 设置画笔为黑色画笔                painter.setPen(QColor::fromRgb(0, 0, 0));                // 绘制数码                painter.drawText(QRectF(7 + (w + 5) * j, 7 + (h + 5) * i, w, h), Qt::AlignCenter,                                 QString::number(board[i][j]));                // 设置画笔为空笔                painter.setPen(Qt::NoPen);            }            // 如果方格中没有数字            else            {                // 设置画刷颜色为 RGB分量为171 165 141的颜色                brush.setColor(QColor::fromRgb(171, 165, 141));                // 应用这个画刷                painter.setBrush(brush);                // 绘制小方格                painter.drawRect(QRectF(7 + (w + 5) * j, 7 + (h + 5) * i, w, h));            }        }}void GameWidget::restart(){    // 初始化相关变量 同构造函数    score = 0;    digitCount = 2;    memset(board, 0, sizeof(board));    board[rand() % 4][rand() % 4] = 2;    while(true) {        int x = rand() % 4;        int y = rand() % 4;        if (board[x][y] != 0) {            continue;        }        else {            board[x][y] = 2;            break;        }    }    emit ScoreInc(score);    update();}bool GameWidget::checkGameOver(){    // 循环检测是否含有相邻的相同数码    for (int i = 0; i < 4; i++)        for (int j = 0; j < 4; j++)        {            if (j != 3 && board[i][j] == board[i][j + 1])                return false;            if (i != 3 && board[i][j] == board[i + 1][j])                return false;        }    return true;}bool GameWidget::checkWin(){    // 循环检测是否某个方格的数字为2048    for (int i = 0; i < 4; i++)        for (int j = 0; j < 4; j++)            if (board[i][j] == 2048)                return true;    return false;}int GameWidget::getBitCount(int n){    // 循环获取数字二进制位数    int c = 0;    while (n >>= 1)        c++;    // 返回位数-1    return c - 1;}
(5)main.cpp
#include "widget.h"#include <QApplication>int main(int argc, char *argv[]){    QApplication a(argc, argv);    Widget w;    w.show();    return a.exec();}

2、运行


四、总结

(1)代码有很些不足,比如一行中有4个相同的数只有相加前2个、开始新游戏没有动画等。
(2)可以参考其他的2048的代码进行修改更新,此源码已经打包上传到csdn上可登录下载(http://download.csdn.net/detail/taiyang1987912/8660527)
(3)若有建议,请留言,在此先感谢!

0 0
原创粉丝点击