简单的做了个数字华容道的小游戏,大概长这样
页面有点简单,但是大概的功能应该差不多都有了。
这个小游戏的难点主要有两个:
① 如何移动?
// 移动算法
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
看到这应该知道了吧。。。
因为我这个例子空格都是出现在最后一位,所以呢 我不管格子列数是奇还是偶,我只要保证 逆序数 为偶数,那么题目就必然有解了 ~_~
上面贴的代码是源码中的两段关键代码,看看就好啦 ~
源码可以分享给广大需要的同胞们,喜欢记得点赞哈