Qt写2048

第一次博客,我将记录用Qt写2048游戏。

程序功能:
0.游戏的开始按钮、重新开始按钮、规则提示
1.格子的左右移动 WASD
2.数字合并时的计算
3.得分计算
4.每次操作后随机出现2
5.判断游戏是否结束
6.游戏界面

设计思路:
0.对于2048这个4*4棋盘的游戏而言,我们可以设计一个int[4][4],于是直接对数组操作即可。
1.初始化函数,使得得分变为0,格子清空
2.随机函数生成2(检测有没有空的格子,若是有,那么直接生成2,如果没有,那么判断游戏是否结束)
3.格子的绘制paintEvent()

接下来,我们开始吧。

0.新建空项目

1.初始化部分

    for(int i=0;i<4;i++){
        for(int j=0;j<4;j++){
            s[i][j]=0;
        }
    }
    button=new QPushButton("开始游戏");
    button->setGeometry(60,400,200,50);
    
    //随机种子
    qsrand(uint(QTime(0,0,0).secsTo(QTime::currentTime())));
    //槽与信号
    connect(button,SIGNAL(clicked()),this,SLOT(slotStart()));

2.绘制格子(此处只贴出设置2和0的格子,其余数字(4,8,16,32......)以此类推,改变数字和颜色即可)

void MainWindow::PaintEvent(QPaintEvent *)
{
    QPainter p(this);
    p.setBrush(Qt::blue);
    p.setFont(QFont("微软雅黑",20,700,false));      //设置字体,颜色

    QString strscore;
    p.drawText(QPoint(20,60),"分数:"+QString::number(score));//显示分数

    //绘制格子
    for(int i=0;i<4;i++){
        for(int j=0;j<4;j++){
            p.setPen(Qt::transparent);
            if(s[i][j]==0){
                p.setBrush(Qt::gray);
                p.drawRect(i*60+40,j*60+120,55,55);

            }
            else if (s[i][j]==2){
                p.setBrush(QColor(255,250,222,255));
                p.drawRect(i*60+40,j*60+120,55,55);
                 p.setPen(Qt::black);
                 p.setFont(QFont("微软雅黑",10,700,false));
                 //在格子中部显示出当前数字,并居中对齐
                 p.drawText(QRectF(i*60+40,j*60+120,55,55),QString::number(2),QTextOption(Qt::AlignCenter));
            }
           
        }
    }
}

3.控制读取键盘,完成数字的移动和相加(此处演示向上移动+相加,左下右以此类推,具体细节见最终源码)

void MainWindow::PressUp()
    {
        //看上方是否为空格,若是,则上移(注意:此处为整体上移)
        for(int i=0;i<4;i++){
            for(int j=1;j<3;j++){
                if(s[i][j]==0) continue;
                for(int p=0;p<j;p++){
                    if(s[i][j]==0){
                        s[i][p]=s[i][j];
                        s[i][j]=0;
                        break;
                    }
                }
            }
        }

        //相加并移动
        for(int i=0;i<4;i++){
            for(int j=0;j<3;j++){
                if(s[i][j]==s[i][j+1]){
                    s[i][j+1]=2*s[i][j];
                    s[i][j]=0;
                    score+=s[i][j];
                    for(int p=j+2;p<4;p++){
                        s[i][p-1]=s[i][p];
                    }
                }
            }
        }
        
    }

4.随机生成2,判断游戏是否结束

最终效果
image
image

源码:
headers:

点击查看代码 headers:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QKeyEvent>
#include <QPushButton>
#include <QPainter>
#include <QTime>
#include <QDebug> //用来 Debug
#include <QMessageBox>//自定义消息提示框


QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT


public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    void paintEvent(QPaintEvent *);
    void keyPressEvent(QKeyEvent *event);

    void PressUp();
    void PressDown();
    void PressLeft();
    void PressRight();
    void myRand();

    QPushButton *button;
    int s[4][4];
    int score=0;
    bool state;

    struct Ns{
        int i;
        int j;
    };


public slots:
        void slotStart();                    //槽函数

private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H


main.cpp:

点击查看代码
#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
                        //显示窗体
    w.setFixedSize(320,480);        //设置窗体固定的长宽
    w.setWindowTitle("2048");       //设置窗体名
    w.show();
    return a.exec();
}

mainwindow.cpp:

点击查看代码
#include "MainWindow.h"
#include "ui_MainWindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //初始化
    for(int i=0;i<4;i++){
        for(int j=0;j<4;j++){
            s[i][j]=0;
        }
    }
    button = new QPushButton("开始游戏",this);
    button->setGeometry(60,400,200,50);//从(60,400)做一个200*50的按钮
    //随机函数
    qsrand(uint(QTime(0,0,0).secsTo(QTime::currentTime())));

    connect(button,SIGNAL(clicked()),this,SLOT(slotStart()));

}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::paintEvent(QPaintEvent *)
{
    QPainter p(this);
    p.setBrush(Qt::blue);
    p.setFont(QFont("微软雅黑",20,700,false));

    QString strscore;
    p.drawText(QPoint(20,60),"分数: "+QString::number(score));

    for (int i=0;i<4;i++) {
        for (int j=0;j<4;j++) {
            p.setPen(Qt::transparent);//?
            if(s[i][j]==0){
                p.setBrush(QColor(255,250,222,255));
                p.drawRect(i*60+40,j*60+120,55,55);
            }
            else if (s[i][j]==2) {
                p.setBrush(QColor(255,229,168,255));
                p.drawRect(i*60+40,j*60+120,55,55);
                p.setPen(Qt::black);
                p.setFont(QFont("微软雅黑",10,700,false));
                //在方块中 绘制Text, 并且文本位置位于中部
                p.drawText(QRectF(i*60+40,j*60+120,55,55),QString::number(2),QTextOption(Qt::AlignCenter));
            }
            else if (s[i][j]==4) {
                p.setBrush(QColor(255,197,136,255));
                p.drawRect(i*60+40,j*60+120,55,55);
                p.setPen(Qt::black);
                p.setFont(QFont("微软雅黑",10,700,false));
                p.drawText(QRectF(i*60+40,j*60+120,55,55),QString::number(4),QTextOption(Qt::AlignCenter));
            }
            else if (s[i][j]==8) {
                p.setBrush(QColor(251,179,129,255));
                p.drawRect(i*60+40,j*60+120,55,55);
                p.setPen(Qt::black);
                p.setFont(QFont("微软雅黑",10,700,false));
                p.drawText(QRectF(i*60+40,j*60+120,55,55),QString::number(8),QTextOption(Qt::AlignCenter));
            }
            else if (s[i][j]==16) {
                p.setBrush(QColor(250,160,99,255));
                p.drawRect(i*60+40,j*60+120,55,55);
                p.setPen(Qt::black);
                p.setFont(QFont("微软雅黑",10,700,false));
                p.drawText(QRectF(i*60+40,j*60+120,55,55),QString::number(16),QTextOption(Qt::AlignCenter));
            }
            else if (s[i][j]==32) {
                p.setBrush(QColor(251,103,55,255));
                p.drawRect(i*60+40,j*60+120,55,55);
                p.setPen(Qt::black);
                p.setFont(QFont("微软雅黑",10,700,false));
                p.drawText(QRectF(i*60+40,j*60+120,55,55),QString::number(32),QTextOption(Qt::AlignCenter));
            }
            else if (s[i][j]==64) {
                p.setBrush(QColor(213,92,14,255));
                p.drawRect(i*60+40,j*60+120,55,55);
                p.setPen(Qt::black);
                p.setFont(QFont("微软雅黑",10,700,false));
                p.drawText(QRectF(i*60+40,j*60+120,55,55),QString::number(64),QTextOption(Qt::AlignCenter));
            }
            else if (s[i][j]==128) {
                p.setBrush(QColor(252,161,159,255));
                p.drawRect(i*60+40,j*60+120,55,55);
                p.setPen(Qt::black);
                p.setFont(QFont("微软雅黑",10,700,false));
                p.drawText(QRectF(i*60+40,j*60+120,55,55),QString::number(128),QTextOption(Qt::AlignCenter));
            }
            else if (s[i][j]==256) {
                p.setBrush(QColor(248,126,124,147));
                p.drawRect(i*60+40,j*60+120,55,55);
                p.setPen(Qt::black);
                p.setFont(QFont("微软雅黑",10,700,false));
                p.drawText(QRectF(i*60+40,j*60+120,55,55),QString::number(256),QTextOption(Qt::AlignCenter));
            }
            else if (s[i][j]==512) {
                p.setBrush(QColor(255,50,80,255));
                p.drawRect(i*60+40,j*60+120,55,55);
                p.setPen(Qt::black);
                p.setFont(QFont("微软雅黑",10,700,false));
                p.drawText(QRectF(i*60+40,j*60+120,55,55),QString::number(512),QTextOption(Qt::AlignCenter));
            }
            else if (s[i][j]==1024) {
                p.setBrush(QColor(188,25,22,255));
                p.drawRect(i*60+40,j*60+120,55,55);
                p.setPen(Qt::black);
                p.setFont(QFont("微软雅黑",10,700,false));
                p.drawText(QRectF(i*60+40,j*60+120,55,55),QString::number(1024),QTextOption(Qt::AlignCenter));
            }
            else if (s[i][j]==2048) {
                p.setBrush(QColor(245,69,67,15));
                p.drawRect(i*60+40,j*60+120,55,55);
                p.setPen(Qt::black);
                p.setFont(QFont("微软雅黑",10,700,false));
                p.drawText(QRectF(i*60+40,j*60+120,55,55),QString::number(2048),QTextOption(Qt::AlignCenter));
            }
            else{
                p.setBrush(Qt::darkBlue);
                p.drawRect(i*60+40,j*60+120,55,55);
                p.setPen(Qt::black);
                p.setFont(QFont("微软雅黑",10,700,false));
                p.drawText(QRectF(i*60+40,j*60+120,55,55),QString::number(s[i][j]),QTextOption(Qt::AlignCenter));
            }
        }
    }
}

void MainWindow::keyPressEvent(QKeyEvent *event)
{
    if(!state){
        return ;
    }
        switch (event->key()) {
        case Qt::Key_W:
            PressUp();
            break;

        case Qt::Key_S:
            PressDown();
            break;

        case Qt::Key_A:
            PressLeft();
            break;

        case Qt::Key_D:
            PressRight();
            break;

        default:
            return;//忽略其他按钮
        }
        myRand();
        update();
}
void MainWindow::slotStart(){
    QMessageBox::about(this,"游戏规则","WSAD控制方块上下左右移动");
    score=0;
    for (int i=0;i<4;i++) {
        for (int j=0;j<4;j++) {
            s[i][j]=0;
        }
    }
    button->setText("重新游戏");

    int randi=qrand()%4;
    int randj=qrand()%4;
    s[randi][randj]=2;

    state=true;
    update();
}
void MainWindow::PressUp(){
    //移动
    for (int i=0;i<4;i++) {
        for (int j=1;j<4;j++) {
            if(s[i][j]==0)continue;
            for (int p=0;p<j;p++) {
                //查看前面是否有空格子可移动
                if(s[i][p]==0){
                    s[i][p]=s[i][j];
                    s[i][j]=0;
                    break;
                }
            }
        }
    }
    //相加
    for (int i=0;i<4;i++) {
        for (int j=0;j<3;j++) {
            if(s[i][j]==s[i][j+1]){
                s[i][j]=2*s[i][j];
                s[i][j+1]=0;
                score+=s[i][j];
                for (int p=j+2;p<4;p++) {
                    s[i][p-1]=s[i][p];
                }
            }
        }
    }
}
void MainWindow::PressDown(){
    //移动
    for (int i=0;i<4;i++) {
        for (int j=2;j>=0;j--) {
            if(s[i][j]==0)continue;
            for (int p=3;p>j;p--) {
                //查看前面是否有空格子可移动
                if(s[i][p]==0){
                    s[i][p]=s[i][j];
                    s[i][j]=0;
                    break;
                }
            }
        }
    }
    //相加
    for (int i=0;i<4;i++) {
        for (int j=3;j>0;j--) {
            if(s[i][j]==s[i][j-1]){
                s[i][j]=2*s[i][j];
                s[i][j-1]=0;
                score+=s[i][j];
                for (int p=j-2;p>=0;p--) {
                    s[i][p+1]=s[i][p];
                }
            }
        }
    }
}
void MainWindow::PressLeft(){
    //移动
    for (int j=0;j<4;j++) {
        for (int i=1;i<4;i++) {
            if(s[i][j]==0){
                continue;
            }
            for (int p=0;p<i;p++) {
                //查看前面是否有空格可移入
                if(s[p][j] == 0){
                    s[p][j] = s[i][j];
                    s[i][j] = 0;
                    break;
                }
            }
        }
    }
    //相加
    for (int j=0;j<4;j++) {
        for (int i=0;i<3;i++) {
            if(s[i][j]==s[i+1][j]){
                s[i][j]=s[i][j]*2;
                score+=s[i][j];
                s[i+1][j]=0;
                for(int p=i+2;p<4;p++){
                    s[p-1][j] = s[p][j];
               }
            }
        }
    }
}
void MainWindow::PressRight(){
    //移动
    for (int j=0;j<4;j++) {
        for (int i=2;i>=0;i--) {
            if(s[i][j]==0){
                continue;
            }
            for (int p=3;p>i;p--) {
                //查看前面是否有空格可移入
                if(s[p][j] == 0){
                    s[p][j] = s[i][j];
                    s[i][j] = 0;
                    break;
                }
            }
        }
    }
    //相加
    for (int j=0;j<4;j++) {
        for (int i=3;i>=0;i--) {
            if(s[i][j]==s[i-1][j]){
                s[i][j]=s[i][j]*2;
                s[i-1][j]=0;
                score+=s[i][j];
                for(int p=i-2;p>=0;p--){
                    s[p+1][j] = s[p][j];
                }
            }
        }
    }
}
void MainWindow::myRand(){
    int i=0,j=0;
    //找出格子
    struct Ns n[15];
    int ni=0;
    for (i=0;i<4;i++) {
        for (j=0;j<4;j++) {
            if(s[i][j]==0){
                n[ni].i=i;
                n[ni].j=j;
                ni++;
            }
        }
    }

    //判断游戏是否结束
    if (ni==0) {
        for (i=0;i<4;i++) {
            for (j=0;j<3;j++) {
                if(s[i][j]==s[i][j+1]){
                    return;
                }
            }
        }
        for (j=0;j<4;j++) {
            for (i=0;i<3;i++) {
                if(s[i][j]==s[i+1][j]){
                    return;
                }
            }
        }
        QMessageBox::about(this,"游戏失败","分数为:"+QString::number(score)+" ");
        return;
    }
    int rand=qrand()%ni;
    s[n[rand].i][n[rand].j]=2;
}

关于Qt写完2048后生成exe文件并运行可以参考这篇文章
Qt生成exe文件并成功运行


本文完

作者:Sky6634

出处:https://www.cnblogs.com/Sky6634/p/16468304.html

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   Sky6634  阅读(181)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示
more_horiz
keyboard_arrow_up light_mode palette
选择主题