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

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];

 

游戏的逻辑原理是什么?

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

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

比方说向右滑动,方向上是横向的,分为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]);

        }

 

结果如下:

 

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

       游戏图(动图太麻烦):

        

 

posted @ 2022-03-13 21:15  敢死法师队队长  阅读(263)  评论(0编辑  收藏  举报