QT-2048小游戏

熟悉QT,将教程里代码稍稍改了一下

哔哩哔哩2048教程——视频里有详细的教程
源文件

一、MainWindow构造函数

1、设置窗口大小及标题

 ui->setupUi(this);
 this->setFixedSize(320,480);
 this->setWindowTitle("2048");

2、按钮
(1)定义3*3和4*4按钮,设置大小,通过connect方法设置游戏的size

 // 3*3按钮
 QPushButton* size_btn_3 = new QPushButton("3X3");
 size_btn_3->move(50,80);
 size_btn_3->setParent(this);
 size_btn_3->setFixedSize(80,30);
 connect(size_btn_3,SIGNAL(clicked()),this,SLOT(ensureSize3()));

 // 4*4按钮
 QPushButton* size_btn_4 = new QPushButton("4X4");
 size_btn_4->setFixedSize(80,30);
 size_btn_4->setParent(this);
 size_btn_4->move(180,80);
 connect(size_btn_4,SIGNAL(clicked()),this,SLOT(ensureSize4()));

(2)确定游戏大小的槽函数

// 3*3
void MainWindow::ensureSize3()
{
    size = 3;
    button->setText("开始游戏");
}

// 4*4
void MainWindow::ensureSize4()
{
    size =4;
    button->setText("开始游戏");
}

3、提示语句
主页面的提示语句

 remind_1 = new QLabel("先选择大小,再点击开始游戏",this);
 remind_2 = new QLabel("WASD控制方向",this);
 
 remind_1->setGeometry(60,150,200,30);
 remind_2->setGeometry(60,170,100,30);

4、开始按钮
定义开始按钮,通过connect方法实现点击开始按钮初始化游戏界面

 // 开始按钮
 button = new QPushButton("开始游戏",this);
 button->setGeometry(60,400,200,50);

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

二、初始化(start槽函数)

1、若未选择size则提示错误并返回

void MainWindow::start(){
    if(size == 0){
        QMessageBox::warning(this,"提示!","请先选择游戏类型!");
        return;
    }

2、设置提示语句为空

    remind_1->setText(" ");
    remind_2->setText(" ");

3、初始化游戏格子及分数,并将按钮值设为重新开始

    score = 0;  // 分数清零
    for(int i = 0;i     < size;i++){
        for(int j = 0;j < size;j++){
            if(size == 3)
                lattice_3[i][j] = 0;
            else if(size == 4)
                lattice_4[i][j] =0;
        }
    }
     button->setText("重新开始");

4、生成随机格子的行与列,再生成随机数2或4填入随机格子中;将状态设为true并update重新刷新界面

    int rand_i = qrand()%size;  // 生成格子的随机行
    int rand_j = qrand()%size;  // 生成格子的随机列

    // 随机生成2,4
    Rand_2_4 rand;
    int rand_number = rand.rand();
    if(size == 3)
        lattice_3[rand_i][rand_j] = rand_number;
    else if(size == 4)
        lattice_4[rand_i][rand_j] = rand_number;
        
    state = true;
	update();
}

三、绘制功能-paintEvent函数

1、绘制背景图片及分数

void MainWindow::paintEvent(QPaintEvent *){
    QPainter paint(this);

    // 设置背景图片
    QPixmap pix;
    pix.load(":/res/background.jpg");
    paint.drawPixmap(0,0,this->width(),this->height(),pix);

    paint.setFont(QFont("微软雅黑",20,700,false));
    QString str_score;
    paint.drawText(QPoint(30,50),"分数    "+QString::number(score));

2、对格子二维数组进行循环,根据格子值设置画刷颜色对格子上色,如果值不为0则将值画出,若为0则不将其画出

    // 格子实现0 2 4 8 16 32 64 128 256 512 1024 2048
    for(int i=0;i < size;i++){
        for(int j=0;j < size;j++){
            paint.setPen(Qt::transparent);
           
            if(size == 3)
                value = lattice_3[i][j];
            else if(size == 4)
                value = lattice_4[i][j];

            // 根据值设置格子刷子颜色
            switch (value) {
                case 0:     paint.setBrush(QBrush(QColor(204,202,202,80)));   break;
                case 2:     paint.setBrush(QBrush(QColor(255,252,227,210)));  break;
                case 4:     paint.setBrush(QBrush(QColor(255,241,140,210)));  break;
                case 8:     paint.setBrush(QBrush(QColor(255,243,26,210)));   break;
                case 16:    paint.setBrush(QBrush(QColor(128,255,252,210)));  break;
                case 32:    paint.setBrush(QBrush(QColor(38,255,250,210)));   break;
                case 64:    paint.setBrush(QBrush(QColor(35,254,150,210)));   break;
                case 128:   paint.setBrush(QBrush(QColor(0,200,60,210)));     break;
                case 256:   paint.setBrush(QBrush(QColor(255,51,51,210)));    break;
                case 512:   paint.setBrush(QBrush(QColor(255,2,2,210)));      break;
                case 1024:  paint.setBrush(QBrush(QColor(96,78,254,210)));    break;
                case 2048:  paint.setBrush(QBrush(QColor(48,24,254,210)));    break;
                default:    paint.setBrush(QBrush(QColor(254,1,159,210)));    break;
            }

            int x = 70,y = 150;
            if(size == 4){
                x = 40;
                y = 120;
            }
            paint.drawRect(i*60+x,j*60+y,55,55); // 对格子上色

            if(value != 0){
                paint.setPen(Qt::black);
                paint.setFont(QFont("微软雅黑",10,700,false));
                //在方块中 绘制Text, 并且文本位置位于中部
              paint.drawText(QRectF(i*60+x,j*60+y,55,55),QString::number(value),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(); // 强制界面刷新
}

五、移动相加

以向上为例,下、左、右均相同

  • 执行先移动再相加
  • 将移动相加分别分为3*3和4*4

1、移动

void MainWindow::pressUp()
{
    // 向上移动
    for(int i = 0;i < size;i++){
        for(int j = 1;j < size;j++){   // 从左上第二行开始向上移动
            // 3*3
            if(size == 3){
                if(lattice_3[i][j] == 0)  // 为0跳过
                    continue;
                    
                for(int k = 0;k < j;k++){
                    if(lattice_3[i][k] == 0){     // 查看上面是否有格子可以移动
                        lattice_3[i][k] = lattice_3[i][j];
                        lattice_3[i][j] = 0;
                        break;
                    }
                }
            }
            // 4*4
            else if(size == 4){
		。。。// 与3*3操作相同
       	    }
	}
    }

2、相加

    // 向上相加
    for(int i = 0;i < size;i++){
        for(int j = 0;j < size;j++){
            // 3*3
            if(size == 3){ // 上面的格子等于下面的格子
                if(lattice_3[i][j] == lattice_3[i][j+1]){
                    lattice_3[i][j] = lattice_3[i][j]*2;  // 上面的格子加倍
                    lattice_3[i][j+1] = 0;              // 下面的格子置0
                    score += lattice_3[i][j];
                    for(int k = j+2;k < size;k++)    // 将后面的格子往前一个格子移栋
                        lattice_3[i][k-1] = lattice_3[i][k];
                }
            }
            // 4*4
            else if(size == 4){
		。。。 // 与3*3操作相同
            }
        }
    }
}

六、寻找空白格子,判断游戏是否结束

1、找出空白格子(即值为0处),并将格子的位置信息存入结构体中

void MainWindow::myrand()
{
    // 找出空白格子
    int i = 0,j = 0;    // 记录空白格子位置
    int number = 0;     // 记录空白格子个数

    // 储存空白格子位置
    struct Position site_3[3*3];
    struct Position site_4[4*4];

    for(i = 0;i < size;i++){
        for(int j = 0;j < size;j++){
            if(size == 3){
                if(lattice_3[i][j] == 0){	// 若为0则代表为空白格子
                    site_3[number].i = i;
                    site_3[number].j = j;
                    number++;
                }
            }
            else if(size == 4){
                if(lattice_4[i][j] == 0){
                    site_4[number].i = i;
                    site_4[number].j = j;
                    number++;
                }
            }
        }
    }

2、判断游戏是否结束

    //判断游戏是否结束
    if (number == 0) {
        // 上下相邻是否有相等的
        for(i = 0;i < size;i++) {
            for(j = 0;j < (size-1);j++) {
                if(size == 3){
                    if(lattice_3[i][j] == lattice_3[i][j+1])
                        return;
                }
                else if(size == 4){
                    if(lattice_4[i][j] == lattice_4[i][j+1])
                        return;
                }
            }
        }
        // 左右相邻是否有相等的
        for(j = 0;j < size;j++) {
            for(i = 0;i < (size-1);i++) {
                if(size == 3){
                    if(lattice_3[i][j] == lattice_3[i+1][j]){
                        return;
                    }
                }
                else if(size == 4){
                    if(lattice_4[i][j] == lattice_4[i+1][j]){
                        return;
                    }
                }
            }
        }
        QMessageBox::warning(this,"Game Over!","游戏结束!");
        return;
    }

3、获取随机的格子,将生成的随机数放入格子

    // 随机获取空白格子
    int site_rand = qrand()%number;

    // 随机生成2,4
    Rand_2_4 ran;
    int rand_number = ran.rand();

    int x,y;
    if(size == 3){
        x = site_3[site_rand].i;
        y = site_3[site_rand].j;
        lattice_3[x][y] = rand_number;
    }
    else if(size == 4){
        x = site_4[site_rand].i;
        y = site_4[site_rand].j;
        lattice_4[x][y] = rand_number;
    }
}

七、效果图

1、主界面

在这里插入图片描述

2、游戏界面

(1)3*3
在这里插入图片描述
(2)4*4
在这里插入图片描述

八、打包

2048
提取码:oxtk

QT.exe程序打包为安装包

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值