2048小游戏

2048小游戏

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_26239525/article/details/82345363

研一时写的2048小游戏C++程序,程序中还有很多值得优化的地方,等以后有时间了再慢慢优化。

编程环境:Based on Qt 5.9.1 (MSVC 2015)。

Github:https://github.com/StayAI/2048

首先要了解2048的游戏规则:

  1. 游戏棋盘为四行四列,很容易想到用二维数组实现,开始时棋盘内随机出现两个数字,出现的数字仅可能为2或4。

  2. 玩家可以选择上下左右四个方向,若棋盘内的数字出现位移或合并,视为有效移动

  3. 玩家选择的方向上若有相同的数字则合并,每次有效移动可以同时合并,但不可以连续合并

  4. 合并所得的所有新生成数字想加即为该步的有效得分

  5. 玩家选择的方向行或列前方有空格则出现位移

  6. 每有效移动一步,棋盘的空位(无数字处)随机出现一个数字(依然可能为2或4)

  7. 棋盘被数字填满,无法进行有效移动,判负,游戏结束

  8. 棋盘上出现2048,判胜,游戏结束

然后总结2048游戏的关键步骤:

  1. 生成二维数组,并初始化:

    int array;
    
    for (int i=0; i<4; i++)
        for (int j=0; j<4; j++)
            array[i][j] = 0;
    
  2. 棋盘内随机出现两个数字,出现的数字仅可能为2或4:

    ex->randomNumber(array);
    ex->randomNumber(array);
    
  3. 判断是否有按键按下,如果有按键按下,需要判断此步是否为有效移动,如果是有效移动,那么进行合并运算:

    1. 判断是否为有效移动,需要先将移动之前的数组拷贝一遍,以便于之后作比较:

      ex->copy(array);
      
    2. 然后判断按下按键方向,进行一系列的运算(主要为游戏规则的3、 4、 5步):

      if (e->key() == Qt::Key_W || e->key() == Qt::Key_Up)
      {
          ex->calculateArrayUp(array);
      }
      if (e->key() == Qt::Key_S || e->key() == Qt::Key_Down)
      {
          ex->calculateArrayDown(array);
      }
      if (e->key() == Qt::Key_A || e->key() == Qt::Key_Left)
      {
          ex->calculateArrayLeft(array);
      }
      if (e->key() == Qt::Key_D || e->key() == Qt::Key_Right)
      {
          ex->calculateArrayRight(array);
      }
      
    3. 判断是否为有效移动,如果是有效移动,则棋盘上随机生成数字(游戏规则6):

      if ( ex->isChange(array) )
      {
          ex->generateNumber(array);
      }
      
    4. 更新显示:

      showArray(array);
      
  4. 判断棋盘是否填满,游戏结束。

    ex->isGameOver(array);
    
  5. 判断棋盘上是否出现2048,游戏胜利。

    ex->isSuccess(array);
    

给出具体代码的实现:

  1. 判断数字是否为有效移动:

    void _2048::copy(int array[][4])//复制数组
    {
        for (int i=0; i<4; i++)
            for (int j=0; j<4; j++)
                array1[i][j] = array[i][j];
    }
    
    
    bool _2048::isChange(int array[][4])//判断数组是否改变
    {
        bool change = false;
    
        for (int i=0; i<4; i++)
            for (int j=0; j<4; j++)
                if (array1[i][j] != array[i][j])
                {
                    array1[i][j] = array[i][j];
                    change = true;
                }
    
        return change;
    }
    
  2. 生成随机数字2或4(2和4出现的频率比是4:1):

    void _2048::randomNumber(int array[][4])
    {
        int t;
    
        qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
        t = qrand()%16;
        while ( array[t/4][t%4] != 0)
        {
            t = qrand()%16;
        }
    
        int seed[7] = {2, 2, 2, 2, 2, 2, 4};
    
        array[t/4][t%4] = seed[qrand()%7];
    }
    
  3. 如果棋盘上未满,就生成数字:

    void _2048::generateNumber(int array[][4])
    {
        int num = 0;
    
        for (int i=0; i<4; i++)
            for (int j=0; j<4; j++)
                if (array[i][j] != 0)
                    num++;
    
        if (num != 16)
        {
            this->randomNumber(array);
        }
    }
    
  4. 判断游戏结束:

    void _2048::isGameOver(int array[][4])
    {
        int num = 0;
    
        for (int i=0; i<4; i++)
            for (int j=0; j<4; j++)
                if (array[i][j] != 0)
                    num++;
                else
                    return;
    
        if (num == 16)
        {
            for(int i=0; i<4; i++)
                for(int j=0; j<3; j++)
                    if (array[i][j] == array[i][j+1])
                        return;
    
            for(int i=0; i<3; i++)
                for(int j=0; j<4; j++)
                    if (array[i][j] == array[i+1][j])
                        return;
    
            qDebug() <<  "GameOver";
        }
    }
    
  5. 判断游戏胜利:

    void _2048::isSuccess(int array[][4])
    {
        for (int i=0; i<4; i++)
            for (int j=0; j<4; j++)
                if (array[i][j] == 2048)
                    qDebug() <<  "Success";
    }
    
  6. 执行具体的操作运算(只给出一个方向上的,其他方向类似):

    注:这个函数比较复杂,主要就是进行运算,感兴趣的拿着纸笔一点一点的算吧。

    void _2048::calculateArrayLeft(int array[][4])
    {
        for (int i=0; i<4; i++)
        {
            int temp[4] = {0, 0, 0, 0};
            int m = 0;
            for (int j=0; j<4; j++)
            {
                if (array[i][j] != 0)
                    temp[m++] = array[i][j];
            }
            for (int j=0; j<4; j++)
            {
                array[i][j] = temp[j];
                temp[j] = 0;
            }
    
            for (int j=0; j<3; j++)
            {
                if ( (array[i][j] == array[i][j+1]) && array[i][j]!=0 )
                {
                    array[i][j] *= 2;
                    this->score += array[i][j];
    
                    for (int k=j+1; k<3; k++)
                    {
                        array[i][k] = array[i][k+1];
                    }
                    array[i][3] = 0;
    
                    break;
                }
            }
        }
    }
    

游戏界面:

这里写图片描述

最好成绩BEST懒得写了,所以一直显示为0。
欢迎交流

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值