如何在JavaScript中生成具有条件的随机数字序列?

时间:2016-07-21 08:56:55

标签: javascript

我试图从1-7生成一系列数字。完全随机。一个数字不能在它前面或后面有一个数字,将它除以1.

一个例子:[2,4,1,6,3,7,5]
NOT:[ 5,4 ,2, 6,7 ,1,3]。
此外, 一个数字不能包含它的位置数 (不是:[1,2,3,4,5,6,7])。

即使我在while循环中陈述了所有这些条件,它也会在不满足所有条件的情况下离开循环。我需要一些帮助来弄清楚问题是什么/更好的方法。

var randomOrder = [];

for (i = 0; i < 7; i++) {
    randomOrder[i] = Math.round(Math.random() * 6 + 1);
    if (i > 0) {
        while ((randomOrder.lastIndexOf(randomOrder[i], i - 1) != -1) && (((randomOrder[i - 1] - 1) != randomOrder[i]) && ((randomOrder[i - 1] + 1) != randomOrder[i]) && (randomOrder[i] != (i + 1))) {
            randomOrder[i] = Math.round(Math.random() * 6 + 1);
        }
        alert(randomOrder.lastIndexOf(randomOrder[i], i - 1));
        alert(randomOrder);
    }
}

4 个答案:

答案 0 :(得分:2)

假设蛮力逼近:

&#13;
&#13;
var list = [ 1, 2, 3, 4, 5, 6, 7 ];

while(
  list.findIndex(function(v, i) {
    return v == i + 1 || (i && Math.abs(list[i - 1] - v) == 1);
  }) != -1
) {
  list.sort(function() { return Math.random() - 0.5; });
}
document.write(list.join(' '));
&#13;
&#13;
&#13;

替代版本

以下是对渐进式填充的尝试&#39;方法

总的来说,它的效率更高,因为它实际上是在尝试构建一个有效的数组,而不仅仅是观察给定的数组是否有效。它包括对不可分割情况的测试,在这种情况下它会立即中止。

build()成功约66%的时间(实证结果),因此平均尝试次数 1.5

相比之下,我的第一种方法在找到有效数据之前平均生成 ~27 数组。

&#13;
&#13;
function build() {
  var remaining = [ 1, 2, 3, 4, 5, 6, 7 ],
      res = [],
      candidate,
      n, sz, sel;

  for(n = 0; n < 7; n++) {
    candidate = remaining.filter(function(v) {
      return v != n + 1 && (!n || Math.abs(res[n - 1] - v) != 1);
    });
    if(!(sz = candidate.length)) {
      return false;
    }
    res.push(sel = candidate[(Math.random() * sz) | 0]);
    remaining.splice(remaining.indexOf(sel), 1);
  }
  return res;
}

while((list = build()) === false) {};
document.write(list.join(' '));
&#13;
&#13;
&#13;

答案 1 :(得分:0)

我会考虑的方法概要:

对于每个位置,计算该位置的可能数字集,并从该列表中随机选择。

位置0该组将是[2 ... 7],在位置1,它将是[1,3 ... 7]减去由于在位置0处的选择而被移除的那些。

如果失败从头开始重新启动,直到它没有(如果某个位置的可能性集为空,则失败)。

答案 2 :(得分:0)

我认为主要问题是使用&amp;&amp; (AND)而不是|| (OR)。

var result = [], current, last = Infinity, i;
while (result.length < 7) {
  i = 0;
  while(++i < 1000 && (!current || result.includes(current) || (current === last - 1) || (current === last + 1) || (current === result.length))) {
    current = 1 + (Math.random() * 7) | 0; // use your floor of choice
  }
  if (i >= 1000) { result.length = 0; continue; }

  result.push(current);
  last = current;
}

答案 3 :(得分:-1)

第7行中

您的代码缺失了)。 这是一个正确循环的固定版本:

var randomOrder = [];

for (i = 0; i < 7; i++) {
    randomOrder[i] = Math.round(Math.random() * 6 + 1);
    if (i > 0) {
        while ((randomOrder.lastIndexOf(randomOrder[i], i - 1) != -1) && (((randomOrder[i - 1] - 1) != randomOrder[i]) && ((randomOrder[i - 1] + 1) != randomOrder[i]) && (randomOrder[i] != (i + 1)))) {
            randomOrder[i] = Math.round(Math.random() * 6 + 1);
        }
        alert(randomOrder.lastIndexOf(randomOrder[i], i - 1));
        alert(randomOrder);
    }
}