微信小程序 《数字华容道》

简单的做了个数字华容道的小游戏,大概长这样

微信小程序 《数字华容道》_第1张图片

页面有点简单,但是大概的功能应该差不多都有了。

这个小游戏的难点主要有两个:

① 如何移动?

// 移动算法
isPass: false, // 是否通关
goMove(e) {
    // 通关 或者 没开始游戏 就不能移动
    if (this.isPass || !this.isStart) return;

    let index = e.currentTarget.dataset.index,   // 当前点击位置
        nowDifficulty = this.data.nowDifficulty, // 当前列数 3 4 5 ...
        numData = this.data.numData, // 题目数组 [12345678]
        step = this.data.step; // 步数

    for (let i in numData) {
        if (index == i) {
            let x = '';
            // 当前点击的 上下左右 方向如果有空位的话,就互换位置
            if (numData[index - nowDifficulty] && numData[index - nowDifficulty].isEmpty) {  // 下
                x = index - nowDifficulty;
            } else if (numData[index + nowDifficulty] && numData[index + nowDifficulty].isEmpty) {  // 上
                x = index + nowDifficulty;
            } else if (numData[index - 1] && numData[index - 1].isEmpty) {  // 左
                // 如果是在最左边的话,禁止向左移动
                for (let h = 1; h < nowDifficulty; h++) {
                    if (index == nowDifficulty * h) return;
                }
                x = index - 1;
            } else if (numData[index + 1] && numData[index + 1].isEmpty) {  // 右
                // 如果是在最右边的话,禁止向右移动
                for (let h = 1; h < nowDifficulty; h++) {
                    if (index == nowDifficulty * h - 1) return;
                }
                x = index + 1;
            } else {
                return; // 没有空位不做任何操作
            }

            // Es6 解构赋值
            [numData[i], numData[x]] = [numData[x], numData[i]];
            step += 1;
            innerAudioContext.play(); // 播放移动效果的音乐
            break;
        }
    }
    this.setData({ step, numData });
    this.gameOver(); // 判断游戏是否结束
},

移动的算法还算简单的,注意以下两点就好:

1、是否可以移动?可以的话就互换位置, 还有超出边界时的判断

2、当前想要移动的位置处在最左边和最右边时的情况,就禁止移动

② 怎样才能让游戏有解?

// 随机打乱题目顺序,并且题目有解
disorganize(numData) {
    let nowDifficulty = this.data.nowDifficulty;
    numData.sort(() => { return (0.5 - Math.random()); }); // 随机打乱顺序
    while (!numData[numData.length - 1].isEmpty) {
        numData.sort(() => { return (0.5 - Math.random()); }); // 当前空格在最后一位就退出循环
    }
    
    let num = 0;
    for (let i = 0; i < numData.length; i++) {
        for (let x = i + 1; x < numData.length; x++) {
            // 计算逆序数总的数量
            if (numData[i].num > numData[x].num) {
                num += 1;
            }
        }
    }

    // 逆序数的数量 必须为偶数才有解
    if (num % 2 == 0) {
        this.setData({ numData });
    } else {
        // 递归调用,直到逆序数的数量为偶数才终止
        this.disorganize(numData);
    }
},

有点麻烦的就是这个了,没想好,很容易入坑。。。

如果是把这些数字随机打乱处理的话,就会出现题目无解的情况,概率一般是50%左右

数字华容道必然有解的前提(网上看到的):

1、若格子列数为奇数,则逆序数必须为偶数

2、若格子列数为偶数,且逆序数为偶数,则当前空格所在行数与初始空格所在行数的差为偶数

3、若格子列数为偶数,且逆序数为奇数,则当前空格所在行数与初始空格所在行数的差为奇数

这里只要正确理解了 逆序数 的概念的话,其他就很容易了,那什么是 逆序数 呢?

在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。一个排列中所有逆序总数叫做这个排列的逆序数。

要怎么数逆序数是多少??

比如:1 2 3 4 5 6 8 7  这组排列中,出现的逆序为:(8 7),那么这组排列的 逆序数 为 1

比如:4 2 3 7 5 6 8 1  这组排列中,出现的逆序为:(4 2) (4 3) (4 1) (2 1) (3 1) (7 5) (7 6) (7 1) (5 1) (6 1) (8 1) ,那么这组排列的 逆序数 为 11

看到这应该知道了吧。。。

因为我这个例子空格都是出现在最后一位,所以呢 我不管格子列数是奇还是偶,我只要保证 逆序数 为偶数,那么题目就必然有解了 ~_~

上面贴的代码是源码中的两段关键代码,看看就好啦 ~ 

源码可以分享给广大需要的同胞们,喜欢记得点赞哈

https://github.com/hujinchen/huarongdao

你可能感兴趣的:(微信小程序,前端,JS)