如何用递归方法缩短代码(或使用其他东西)?



代码应该为游戏创建获胜条件。想象一个包含64个数字的数组:(0…63)。代码每4个数字切割这个数组,然后将它们洗牌:(0,1,2,3)=>(1,0,3,2)等等。主要部分是遍历这些数字:

  • 我们从第一组中选择第一个数字并继续(在本例中为1)并将其推送到获胜条件数组(最终数组);
  • 在第二个随机集(5,4,7,6)上,我们也选择第一个数字,但我们应该检查这个数字是否与之前的数字不同(因此,0是第一个,1是第二个等等;4是第一,5是第二,等等)。数字5在同一个位置,所以我们应该选择数组中的下一个数字,在这个例子中是4。4符合条件,所以我们继续;
  • 有第三个集合(8,9,11,10),在这里我们重复前面的操作来检查元素在这个集合中的位置是否与前面的集合中的位置相同!8是1,4是1,所以我们把它换成下一个数字- 9。但这里有一个复杂的问题——我们也应该检查第一组。9是第二名,1是第二名,所以我们移动到下一个数字,即11;
  • 在set的最后一次迭代中,我们重复上述所有过程,用数组中的1检查前面集合的每个数字。我们在第二次尝试时从(12,15,13,14)中选择15;
  • 每16个数字重新开始。

最后一个数组将是这样的(1,4,11,15,16,…,61),其中包含16个数字。

我已经编写了工作良好的所需代码,但我希望它更智能、更短。我知道答案需要递归方法,但我不知道如何使用它。

下面是代码本身:

let currDiff = 4;
function createWinCond() {
let numb = []
let winNum = []
winCond = []
for (let i = 0; i < currDiff * currDiff * currDiff; i++) {
numb.push(i) //array with numbers from 0 to 63
if (numb.length % currDiff == 0) {
winNum = shuffle(numb) // I have a function that shuffles those numbers
for (let j = 0; j < currDiff; j++) {
if (winCond[j] == undefined || winCond.length % currDiff == 0) {
winCond.push(winNum[j]);
break;
}
if ((winCond.length + currDiff) % currDiff == 1 && winCond[winCond.length - 1] != (winNum[j] - currDiff)) {
winCond.push(winNum[j]);
break;
}
if ((winCond.length + currDiff) % currDiff == 2 && winCond[winCond.length - 1] != (winNum[j] - currDiff) && winCond[winCond.length - 2] != (winNum[j] - currDiff * 2)) {
winCond.push(winNum[j]);
break;
}
if ((winCond.length + currDiff) % currDiff == 3 && winCond[winCond.length - 1] != (winNum[j] - currDiff) && winCond[winCond.length - 2] != (winNum[j] - currDiff * 2) && winCond[winCond.length - 3] != (winNum[j] - currDiff * 3)) {
winCond.push(winNum[j]);
break;
}                
}
numb = [];
winNum = [];
}
}

如果你有任何想法可以写得更好,请告诉我。

我想我理解你正在使用的规则,如果是这样,那么是的,这可以简化很多。这是我的想法:从每16个独立的组中,我们将考虑4个组,我们将为这些组中的元素选择的索引将是集合{0, 1, 2, 3}的一个排列。这种排列可以从24种可能性中随机选择。

通过收集这24个分区并编写一个快速函数来随机选择其中一个分区,我们可以非常简单地编写这个函数:

const perms = [[0, 1, 2, 3], [0, 1, 3, 2], [0, 2, 1, 3], [0, 2, 3, 1], [0, 3, 1, 2], [0, 3, 2, 1], 
[1, 0, 2, 3], [1, 0, 3, 2], [1, 2, 0, 3], [1, 2, 3, 0], [1, 3, 0, 2], [1, 3, 2, 0], 
[2, 0, 1, 3], [2, 0, 3, 1], [2, 1, 0, 3], [2, 1, 3, 0], [2, 3, 0, 1], [2, 3, 1, 0], 
[3, 0, 1, 2], [3, 0, 2, 1], [3, 1, 0, 2], [3, 1, 2, 0], [3, 2, 0, 1], [3, 2, 1, 0]]
const randomPerm = () => perms [Math .floor (Math .random () * perms .length)]
const createWinCond = () => 
[0, 1, 2, 3] .flatMap ((i) => randomPerm () .map ((j, k) => 16 * i  + 4 * k + j))
console .log (createWinCond ())
.as-console-wrapper {max-height: 100% !important; top: 0}

我们将组合三个值i,jk,每个取03之间的值。所以i代表16个基团。对于其中的每一个,我们选择一个随机排列,并映射到这些值,我们将让k表示到该分区的索引,也就是说,表示16个组中的4个组,j表示该组中的实际索引值。,16i + 4k + j给出了我们的值。

注意,我们需要做的唯一随机调用是选择随机排列。我们不需要洗牌。更重要的是,我们不需要测试我们是否在块中重用了索引。

为了简化,我们可能更喜欢使用permutations函数来生成这些初始排列,或者我们可能更喜欢这样的版本:

const perms = `0123 0132 0213 0231 0312 0321 1023 1032 1203 1230 1302 1320
2013 2031 2103 2130 2301 2310 3012 3021 3102 3120 3201 3210`
.split (/s+/) .map (p => p.split ('') .map (Number))

我不能100%确定我已经捕获了您的需求,但感觉我好像已经捕获了,而且这明显更简单。

最新更新