2048:数字移动的逻辑实现原理

前言:

         本文主要讲解2048的游戏实现原理,包括游戏数字移动部分的游戏逻辑实现。

         本人目前还处于 Cocos Cerator 游戏引擎的学习阶段,我做了个2048游戏的项目,看似简单,但整个游戏开发也学习了很多。

         在网上搜索关于2048游戏实现原理的文章中,很多是直接给出一个界面的当前状态,触摸操作后运行处理只得到一个终态,2048在手指滑动同时界面直接变化,用户体验感觉不佳。

         那么,怎么能在处理数字移动合并的同时,将数字移动的部分记录下来呢?

问题解决:

游戏的存储方式是什么?

         游戏在存储结构上采用1维数组来实现数据存储,为方便后面统一称‘数字数组’。

并且,想要让数字能够体现移动效果,那么还需要有数据来存储每个数字的移动,这里也用1维数组来存储,其中,每个索引存储的是数字数组对应索引上移动的格数,为方便统一称为‘移动数组’。代码如下:

 

//数字数组
let numArray = [
0, 2, 2, 0,
4, 0, 2, 2,
2, 2, 0, 4,
0, 4, 0, 2];
//移动数组
let moveArray = [
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0];

 

游戏的逻辑原理是什么?

2048代码python 2048代码逻辑图_bc

数字数组如何移动和合并呢?

在方法里上下左右四个方向一样操作,变换数组索引(起始位置和下一数字索引步长)就行。

比方说向右滑动,方向上是横向的,分为4行处理,第一行起始点索引为0,步长为1;第二行起始点为4,步长为1。向上滑动,方向上是纵向的,分为4行处理,第一列起始点索引为0,步长为4。

例如向右滑动,分4行处理,从右边到左边依次判断,每个数字先移动,右方有空位向右移动,直至不能移动位置后再合并:数字左方依次判断,不为空并且相等就合并。

我写了一个方法来处理数字数组,并按对应的起始点索引和步长处理数字移动,并修改传入的移动数组。代码如下:

 

 

move(ks: number, bc: number, numArray: number[], moveArray: number[]) {
        let newNumArray = numArray.slice();
        for (let i = 3; i >= 0; i--) {//为空跳过判断
            if (newNumArray[ks + i * bc] !== 0) {
                for (let j = i; j < 4; j++) {//先移位,将移动的数值加入移动数组moveArray,更新数字数组numArray
                    if (j < 3 && newNumArray[ks + (j + 1) * bc] === 0) {
                        moveArray[ks + i * bc] += bc > 0 ? -1 : 1;
                        newNumArray[ks + (j + 1) * bc] = newNumArray[ks + j * bc];
                        newNumArray[ks + j * bc] = 0;
                        continue;
                    }
                    else if (j >= 3 || newNumArray[ks + (j + 1) * bc] !== 0) {//在角落或不能移位后就合并
                        for (let k = j; k > 0; k--) {
                            if (newNumArray[ks + (k - 1) * bc] !== 0) {//不为空判断,为空跳过
                                if (newNumArray[ks + (k - 1) * bc] === newNumArray[ks + j * bc]) {//合并,数组更新,将移动的数值加入移动数组moveArray
                                    newNumArray[ks + (k - 1) * bc] = 0;
                                    newNumArray[ks + j * bc] = newNumArray[ks + j * bc] * 2;
                                    moveArray[ks + (k - 1) * bc] += (bc > 0 ? -1 : 1) * (j - (k - 1));
                                }
                                break;
                            } else {
                                continue;
                            }
                        }
                        break;
                    }
                }
            }
        }
    }

 

例子:调用向右滑动

 

//数字数组
        let numArray = [
            0, 2, 2, 0,
            4, 0, 2, 2,
            2, 2, 0, 4,
            0, 4, 0, 2];
        //移动数组
        let moveArray = [
            0, 0, 0, 0,
            0, 0, 0, 0,
            0, 0, 0, 0,
            0, 0, 0, 0];
        cc.log('-传入数字数组如下-');
        for (let x = 0; x < 4; x++) {
            cc.log(numArray[x * 4] + ' '
                + numArray[x * 4 + 1] + ' '
                + numArray[x * 4 + 2] + ' '
                + numArray[x * 4 + 3]);
        }
        //向右滑动
        this.move(0, -1, numArray, moveArray);
        this.move(4, -1, numArray, moveArray);
        this.move(8, -1, numArray, moveArray);
        this.move(12, -1, numArray, moveArray);
        cc.log('-修改移动数组如下-');
        for (let x = 0; x < 4; x++) {
            cc.log(moveArray[x * 4] + ' '
                + moveArray[x * 4 + 1] + ' '
                + moveArray[x * 4 + 2] + ' '
                + moveArray[x * 4 + 3]);
        }

 

结果如下:

 

2048代码python 2048代码逻辑图_实现原理_02

         最后,用移动数组将每个移动的数字节点先移动到对应的位置,再将同个位置下重复的数字节点一个消除一个数字加倍,就能得到移动的效果了。

       游戏图(动图太麻烦):

        

2048代码python 2048代码逻辑图_实现原理_03