• 基于C++和QT开发实现的2048小游戏


    资源下载地址:https://download.csdn.net/download/sheziqiong/85788151
    资源下载地址:https://download.csdn.net/download/sheziqiong/85788151

    基于C++设计的2048小游戏

    1. 作业题目

    2048小游戏:通过上下左右键合并数字块,合并得出2048时,游戏胜利;当上下左右操作均无法移动任一数字块,游戏失败。

    2. 开发软件

    系统环境: Windows 10

    开发环境: Qt Creator 4.3.1

    编译器环境: MinGW 5.3.0 32bit (C/C++)

    Qt依赖版本: Qt 5.9.0

    3. 课题要求

    学生自选题目,使用C++语言完成一个图形化的小程序。

    图形化平台不限,可以是MFC、QT等。

    程序内容主题不限,可以是小游戏、小工具等。

    4. 主要流程

    4.1 绘制游戏窗口:

    4.1.1 QWidget:

    Widget是Qt中创建用户界面的主要元素,它可以显示数据和状态信息,接收用户输入,并为其他应该组合在一起的Widget提供一个容器(可以堆叠盛放其他的Widgets)。最外层的Widget称为Window。

    GameBoard::GameBoard(QWidget *parent) : // 由Qwidget继承来的组件
        QWidget(parent)
    
    • 1
    • 2

    在创建游戏面板时,我们在文件初始创建时就可以选中继承对象QWidget

    在这里插入图片描述

    4.1.2 QLayout:

    • QLayout提供了便捷的页面布局方法:
      1. QHBoxLayout将Widget按水平排列,从左到右。
      2. QVBoxLayout将Widget按垂直排列,从上到下。
      3. QGridLayout在二维网格中布局Widget。Widget可以占用多个单元格。
        // 设置主窗口垂直布局
        mainLayout = new QVBoxLayout(); // QLayout将Widget呈现垂直排列
        setLayout(mainLayout);
    
        // 创建游戏面板为网格状布局
        boardLayout = new QGridLayout(); // QLayout将Widget呈现二维网格排列
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    4.1.3 QLabel:

    • QLabel用于显示文本或图像。不提供用户交互功能。
    • QLabel可以使用类似CSS的样式设置,通过方法setStyleSheet启用样式设置
        auto cell = new QLabel();
        cell->setText("2");
        cell->setAlignment(Qt::AlignCenter);
        cell->setStyleSheet("QLabel { background: rgb(238,228,218); color: rgb(119,110,101); font: bold; border-radius: 10px; font: 40pt; }");
    
    • 1
    • 2
    • 3
    • 4
    • 上面代码将cell定义为一个QLabel,设置块中文本为2,居中,同时设置了QLabel样式,对颜色、背景和字体进行进一步调整。

    4.1.4 显示分数:

    • 在游戏面板下方,显示分数score,且右对齐。
    // 加入score显示模块
        score = new QLabel(QString("SCORE: %1").arg(0)); // 用QLabel显示分数score
        score->setStyleSheet("QLabel { color: rgb(235,224,214); font: 16pt; }"); // 设置样式
        score->setFixedHeight(50); // 高度自适应
        mainLayout->insertWidget(1, score, 0, Qt::AlignRight); // 在主窗口中插入分数模块
    
    • 1
    • 2
    • 3
    • 4
    • 5

    4.1.5 绘制4*4网格布局:

    • 4*4的生成采用循环语句。由于游戏中需要对数字块进行多次绘制并具备初始化功能,所以抽象为drawBoard()函数代替。
    void GameBoard::drawBoard()
    {
        delete boardLayout;
        boardLayout = new QGridLayout();
        for (int i = 0; i < NCells; ++i) {
            for (int j = 0; j < NCells; ++j) {
                delete cells[i][j];
                cells[i][j] = new Cell(game.board[i][j]);
                boardLayout->addWidget(cells[i][j], i, j);
                cells[i][j]->draw();
            }
        }
        mainLayout->insertLayout(0, boardLayout);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    4.2 绘制数字块:

    • 数字块可以命名为Cell,是QLabel类型的,可以显示文本并设置样式
    • 在文件创建时,可以设置为继承QLabel
    • cell类声明了draw()成员函数,用于设置网格的样式。
    Cell::Cell(int v): value(v)
    {
        setAlignment(Qt::AlignCenter);
    }
    
    void Cell::draw() //draw()函数可以按照cell不同的值来设置样式
    {
        setText(QString::number(value));
        auto style = QString("Cell { background: %1; color: %2; font: bold; border-radius: 10px; font: 40pt; }");
        switch (value) {
        case 2: {
            setStyleSheet(style.arg("rgb(238,228,218)").arg("rgb(119,110,101)"));
            break;
        }
        case 4: {
            setStyleSheet(style.arg("rgb(237,224,200)").arg("rgb(119,110,101)"));
            break;
        }
        case 8: {
            setStyleSheet(style.arg("rgb(242,177,121)").arg("rgb(255,255,255)"));
            break;
        }
        case 16: {
            setStyleSheet(style.arg("rgb(245,150,100)").arg("rgb(255,255,255)"));
            break;
        }
        case 32: {
            setStyleSheet(style.arg("rgb(245,125,95)").arg("rgb(255,255,255)"));
            break;
        }
        case 64: {
            setStyleSheet(style.arg("rgb(245,95,60)").arg("rgb(255,255,255)"));
            break;
        }
        case 128: {
            setStyleSheet(style.arg("rgb(237,207,114)").arg("rgb(255,255,255)"));
            break;
        }
        case 256: {
            QGraphicsDropShadowEffect *dse = new QGraphicsDropShadowEffect();
            dse->setColor(Qt::yellow);
            dse->setBlurRadius(20);
            dse->setOffset(-1);
            setGraphicsEffect(dse);
            setStyleSheet(style.arg("rgb(237,204,97)").arg("rgb(255,255,255)"));
            break;
        }
        case 512: {
            QGraphicsDropShadowEffect *dse = new QGraphicsDropShadowEffect();
            dse->setColor(Qt::yellow);
            dse->setBlurRadius(30);
            dse->setOffset(-1);
            setGraphicsEffect(dse);
            setStyleSheet(style.arg("rgb(237,204,97)").arg("rgb(255,255,255)"));
            break;
        }
        case 1024: {
            QGraphicsDropShadowEffect *dse = new QGraphicsDropShadowEffect();
            dse->setColor(Qt::yellow);
            dse->setBlurRadius(40);
            dse->setOffset(-1);
            setGraphicsEffect(dse);
            setStyleSheet(style.arg("rgb(237,204,97)").arg("rgb(255,255,255)"));
            break;
        }
        case 2048: {
            QGraphicsDropShadowEffect *dse = new QGraphicsDropShadowEffect();
            dse->setColor(Qt::yellow);
            dse->setBlurRadius(50);
            dse->setOffset(-1);
            setGraphicsEffect(dse);
            setStyleSheet(style.arg("rgb(237,204,97)").arg("rgb(255,255,255)"));
            break;
        }
        default: {
            setText("");
            setStyleSheet("Cell { background: rgb(204,192,179); border-radius: 10px; }");
        }
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 在设置Cell样式时,还使用了QString来构建字符串。可以使用arg()重载函数来访问值。取得Label的值后,根据值的不同设置不同样式。

    • 可以在main.cpp中设置随机数srand(time(NULL));,使得每次打开应用都不一样。

    5. 单元测试:

    5.1 绘制游戏窗口:

    • 初始QWidget绘制效果如下(仅包含一个窗口和一个文字QLabel):

    在这里插入图片描述

    • 在下方加入score后效果如下:

    在这里插入图片描述

    • 设置循环后,绘制4*4网格如下:

    在这里插入图片描述

    5.2 绘制数字块:

    • 为之前创建的4*4网格上,进行样式整理,结果如下:
      在这里插入图片描述

    5.3 游戏逻辑展示:

    • 游戏过程:

    在这里插入图片描述

    • 游戏胜利:

    在这里插入图片描述

    • 游戏失败:

    在这里插入图片描述

    资源下载地址:https://download.csdn.net/download/sheziqiong/85788151
    资源下载地址:https://download.csdn.net/download/sheziqiong/85788151

  • 相关阅读:
    【动态规划】--买卖股票的最佳时机
    对人工智能技术GPT-4o的初步认知
    智能矩阵系统解决的问题?
    【深度学习】实验08 TensorBoard案例
    95后工程师上班哼小曲?那些愉快上班的打工人,到底怎么做到的?
    针对舆情分析近五年参考文献的分析报告
    计算机视觉的应用13-基于SSD模型的城市道路积水识别的应用项目
    ControlNet原理及应用
    神经气体网络(NGN)和不断增长的神经气体网络(GNGN)研究(Matlab代码实现)
    Fresco 图片框架简单使用
  • 原文地址:https://blog.csdn.net/newlw/article/details/125473689