开发 | 「小游戏」开发难?不妨先从 2048 入手试试看

开发 | 「小游戏」开发难?不妨先从 2048 入手试试看
作者:windlany最近流行微信「跳一跳」小游戏,我也心血来潮写了一个微信小程序版 2048,本篇文章主要分享实现 2048 的算法以及注意的点,一起来学习吧!开发 | 「小游戏」开发难?不妨先从 2048 入手试试看


开发 | 「小游戏」开发难?不妨先从 2048 入手试试看

算法

  • 生成 4*4 棋盘视图

  • 随机生成 2 或 4 填充两个单元格

  • 记录用户 touch 时的起始位置和结束位置,以此判断滑动方向

  • 根据滑动方向移动单元格,并进行相同值合并

  • 用户一次滑动完成后重复执行步骤 2

  • 判断游戏是否结束,并根据游戏结果产生不同提示

  • 难点

  • 确定滑动方向

  • 用户滑动时,相同格子合并,并移到滑动方向一侧

  • 视图实现

    1. 用 WXML + WXSS 生成棋盘视图

    开发 | 「小游戏」开发难?不妨先从 2048 入手试试看

    2. 用 

    wx:for

     将数据渲染到每个单元格

    逻辑实现

    1. 页面加载完毕随机用数字 2 或 4 填充两个单元格

    2. 判断用户滑动方向

  • 使用 

    touchStart

     事件函数获取起始位置 

    touchStartX

    touchStartY

  • 使用 

    touchMove

     事件函数获取终点位置 

    touchEndX

    touchEndY

  • var

    disX =

    this

    .touchStartX -

    this

    .touchEndX;

    var

    absdisX =

    Math

    .abs(disX);

    var

    disY =

    this

    .touchStartY -

    this

    .touchEndY;

    var

    absdisY =

    Math

    .abs(disY);  



    // 确定移动方向



    // 0:上, 1:右, 2:下, 3:左



    var

    direction = absdisX > absdisY ? (disX <

    0

    ?

    1

    :

    3

    ) : (disY <

    0

    ?

    2

    :

    0

    );

    3. 根据滑动方向(假设向右滑动)移动表格以及相同项合并

    将 2048 的棋盘生成 4*4 的二维数组 list,为空的空格用 0 表示

    var

    grid = [

       [

    2

    ,

    2

    ,

    0

    ,

    0

    ],

       [

    0

    ,

    0

    ,

    0

    ,

    0

    ],

       [

    0

    ,

    8

    ,

    4

    ,

    0

    ],

       [

    0

    ,

    0

    ,

    0

    ,

    0

    ]

    ];根据滑动方向生成 4*4 二维数组

    var

    list = [

       [

    0

    ,

    0

    ,

    2

    ,

    2

    ],

    // 注意是0022不是2200,因为像右滑动所以从右边push入数组



       [

    0

    ,

    0

    ,

    0

    ,

    0

    ],

       [

    0

    ,

    4

    ,

    8

    ,

    0

    ],

       [

    0

    ,

    0

    ,

    0

    ,

    0

    ]

    ]

    相应代码(代码中 

    this.board.grid

     为上面的初始 grid):

    formList(dir) {  

    // 根据滑动方向生成list的四个数组



     

    var

    list = [[], [], [], []];

     

    for

    (

    var

    i =

    0

    ; i <

    this

    .size; i++)

       

    for

    (

    var

    j =

    0

    ; j <

    this

    .size; j++) {

         

    switch

    (dir) {

           

    case

    0

    :

             list[i].push(

    this

    .board.grid[j][i]);

             

    break

    ;

           

    case

    1

    :

             list[i].push(

    this

    .board.grid[i][

    this

    .size -

    1

    - j]);

             

    break

    ;

           

    case

    2

    :

             list[i].push(

    this

    .board.grid[

    this

    .size -

    1

    - j][i]);

             

    break

    ;

           

    case

    3

    :

             list[i].push(

    this

    .board.grid[i][j]);

             

    break

    ;

         }

       }

     

    return

    list;

    }

    将 list 的每一个小数组中的数字提到前面,0 放到末尾

    list2 = [

        [

    2

    ,

    2

    ,

    0

    ,

    0

    ],

       [

    0

    ,

    0

    ,

    0

    ,

    0

    ],

       [

    4

    ,

    8

    ,

    0

    ,

    0

    ],

       [

    0

    ,

    0

    ,

    0

    ,

    0

    ]

    ];

    相应代码:

    changeItem(item) {  

    // 将 [0, 2, 0, 2] 改为 [2, 2, 0, 0]



       

    var

    cnt =

    0

    ;

       

    for

    (

    var

    i =

    0

    ; i < item.length; i++)

         

    if

    (item[i] !=

    0

    )

           item[cnt++] = item[i];

       

    for

    (

    var

    j = cnt; j < item.length; j++)

         item[j] =

    0

    ;

       

    return

    item;

     }将相同值的单元格加起来,并将后面的一个单元格值变为 0list2 = [

        [

    4

    ,

    0

    ,

    0

    ,

    0

    ],

       [

    0

    ,

    0

    ,

    0

    ,

    0

    ],

       [

    4

    ,

    8

    ,

    0

    ,

    0

    ],

       [

    0

    ,

    0

    ,

    0

    ,

    0

    ]

    ];

    相应代码:

    combine(list) {

    // 滑动时相同的合并



     

    for

    (

    var

    i =

    0

    ; i < list.length; i++)  

    // 数字靠边



       list[i] =

    this

    .changeItem(list[i]);



     

    for

    (

    var

    i =

    0

    ; i <

    this

    .size; i++) {

       

    for

    (

    var

    j =

    1

    ; j <

    this

    .size; j++) {

         

    if

    (list[i][j -

    1

    ] == list[i][j] && list[i][j] !=

    ""

    ) {

           list[i][j -

    1

    ] += list[i][j];

           list[i][j] =

    ""

    ;

         }

       }

     }

     

    for

    (

    var

    i =

    0

    ; i < list.length; i++)  

    // 再次数字靠边



       list[i] =

    this

    .changeItem(list[i]);

     

    return

    list;

    }

    将 list2 回退为 list 并渲染数据到棋盘视图

    list = [

        [

    0

    ,

    0

    ,

    0

    ,

    4

    ],

       [

    0

    ,

    0

    ,

    0

    ,

    0

    ],

       [

    0

    ,

    0

    ,

    8

    ,

    4

    ],

       [

    0

    ,

    0

    ,

    0

    ,

    0

    ]

    ];

    相应代码:

    move(dir) {

     

    // 0:上, 1:右, 2:下, 3:左



     

    var

    curList =

    this

    .formList(dir);

     

    var

    list =

    this

    .combine(curList);

     

    var

    result = [[], [], [], []];



     

    for

    (

    var

    i =

    0

    ; i <

    this

    .size; i++)

       

    for

    (

    var

    j =

    0

    ; j <

    this

    .size; j++) {

         

    switch

    (dir) {

           

    case

    0

    :

             result[i][j] = list[j][i];

             

    break

    ;

           

    case

    1

    :

             result[i][j] = list[i][

    this

    .size -

    1

    - j];

             

    break

    ;

           

    case

    2

    :

             result[i][j] = list[j][

    this

    .size -

    1

    - i];

             

    break

    ;

           

    case

    3

    :

             result[i][j] = list[i][j];

             

    break

    ;

         }

       }

     

    this

    .board.grid = result;

     

    this

    .setDataRandom();



     

    return

    result;

    }

    4. 重复步骤 1



    5. 判断游戏是否结束

    判断标准:4*4 单元格填满且任意一个单元格上下左右没有相同值的单元格isOver() {  

    // 游戏是否结束,结束条件:可用格子为空且所有格子上下左右值不等



     

    this

    .board.__proto__ =

    this

    .bproto;

     

    if

    (!

    this

    .board.cellEmpty()) {

       

    return

    false

    ;

     }

    else

    {

       

    for

    (

    var

    i =

    0

    ; i <

    this

    .size; i++)

    // 左右不等



         

    for

    (

    var

    j =

    1

    ; j <

    this

    .size; j++) {

           

    if

    (

    this

    .board.grid[i][j] ==

    this

    .board.grid[i][j -

    1

    ])

             

    return

    false

    ;

         }

       

    for

    (

    var

    j =

    0

    ; j <

    this

    .size; j++)  

    // 上下不等



         

    for

    (

    var

    i =

    1

    ; i <

    this

    .size; i++) {

           

    if

    (

    this

    .board.grid[i][j] ==

    this

    .board.grid[i -

    1

    ][j])

             

    return

    false

    ;

         }

     }

     

    return

    true

    ;

    }

    6. 根据游戏结果给出相应提示



    开发 | 「小游戏」开发难?不妨先从 2048 入手试试看

    开发 | 「小游戏」开发难?不妨先从 2048 入手试试看

    原文地址:

    http://juejin.im/post/5a6690dd518825732c53ace5

    关注「

    知晓程序

    」微信公众号,回复「

    开发

    」,让你的小程序性能再上一层楼。

    开发 | 「小游戏」开发难?不妨先从 2048 入手试试看


    ▽ 点击「

    阅读原文

    」,发现更多优质小程序。