5

我在这里搜索了一些答案,但它似乎不是我需要的东西,或者我只是不知道如何应用它。

我还没有开始任何代码,我只是在想怎么做,我不知道怎么做。我需要你们的帮助。

假设我有一个由以下这些值组成的数组

[1,2,3,4,5,6,7,8,9]

而且我需要在不重复最后一个结果的每个数字的位置的情况下对其进行洗牌。所以它可能会喜欢

[5,3,9,6,2,8,1,4,7]

如果我再次洗牌它会像

[4,7,2,1,8,3,6,9,5]

等等。

好吧,我不知道是否与它有任何相关性,但是,我宁愿不使用rand()。这东西有什么解决办法吗?

4

6 回答 6

2

试试这个,

$count = 15;
$values = range(1, $count);
shuffle($values);
$values = array_slice($values, 0, 15);

或者

$numbers = array();
do {
   $possible = rand(1,15);
   if (!isset($numbers[$possible])) {
      $numbers[$possible] = true;
   }
} while (count($numbers) < 15);
print_r(array_keys($numbers));

这可以帮助你。

于 2013-02-21T13:50:39.850 回答
1

您要做的是将数组中的元素随机添加到另一个数组,但要确保元素不在相同的索引位置。试试这个:

$array = [1,2,3,4,5,6,7,8,9];
$new = array();
for($i = 0; $i < $array.length; $i++){
  $rand = $i;
  do {
    $rand = Math.floor( Math.random() * ( $array.length + 1 ) );
  } while ($rand == $i || array_key_exists($rand, $new))
  // Check that new position is not equal to current index
  // and that it doesnt contain another element

  $new[$rand] = $array[i];
}

不是最有效的,但保证将元素放在不同的索引中。

于 2013-02-21T14:04:07.857 回答
1

您可以使用Fisher-Yates-Shuffle的变体,它会随机选择交换的元素,称为Sattolo 算法

function shuffleArray(array) {
    for (var i = array.length - 1; i > 0; i--) {
        var j = Math.floor(Math.random() * i); // no +1 here!
        var temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }
    return array;
}

这样,可以保证每个元素都被交换并且不会出现在与以前相同的位置。

于 2013-02-21T14:57:36.403 回答
0

这使得数组的值不会重复 n 次随机播放的任何先前位置(我使用数组大小​​的一半作为 n,之后我重新启动禁止索引)。最后修改了这个版本,使其不重复当前位置。

为此,您必须保存原始数组的每个值所在的所有索引的历史记录。为此,我为您的数字增加了一点复杂性

var numberArray = [{value:1, unavailable_indexes:[0]},
                   {value:2, unavailable_indexes:[1]},
                   {value:3, unavailable_indexes:[2]},
                   {value:4, unavailable_indexes:[3]},
                   {value:5, unavailable_indexes:[4]},
                   {value:6, unavailable_indexes:[5]},
                   {value:7, unavailable_indexes:[6]},
                   {value:8, unavailable_indexes:[7]},
                   {value:9, unavailable_indexes:[8]}
                  ];

这样你就有了值中的数字和它所在的所有位置的数组。接下来我们需要运行所有数组并切换数字。

var arrayLen = numberArray.length-1;
$.each(numberArray, function(index, value){
    var newIndex;
    //restart the array when half of the index have been covered or it will take awhile to get a random index that wasn't used
    if(value.unavailable_indexes.length >= numberArray.length/2)
        value.unavailable_indexes = [index];//restart the unavailable indexes with the current index as unavailable
    do{
        newIndex = Math.floor(Math.random()*arrayLen);
    //verify if you can swap the 2 values, if any of them have been on the destination index get another random index
    }while($.inArray(value.unavailable_indexes, newIndex) || $.inArray(numberArray[newIndex].unavailable_indexes, index));


    numberArray[index] = numberArray[newIndex];
    numberArray[newIndex] = value;
})

在所有阵列移动后,您需要保存它们降落的位置

$.each(numberArray, function(index, value){
   value.unavailable_indexes.push(index);
}

编辑:如果你只是想防止它只是重复以前的位置然后unavailable_indexes保持它的最后一个位置并替换为do{...}while()

do{
    newIndex = Math.floor(Math.random()*arrayLen);
}while(newIndex != value.unavailable_indexes)

最后一种方法看起来像:

$.each(numberArray, function(index, value){
   value.unavailable_indexes = index;
}
于 2013-02-21T13:50:04.907 回答
0

我刚刚想出了以下代码,以解决我遇到的一个问题,有时我的随机打乱的数组会以原始顺序结束(是随机了,还是不够随机)。

它是如何工作的,它在一个 while 循环上循环,直到 $isDifferent 变量变为真,这只有在数组不匹配时才会发生。这可能与 Fisher-Yates 方法的工作方式类似,尽管当我尝试这样做时,有时我仍然会得到匹配的数组。

这个解决方案是用 PHP 编写的,但可以很容易地转换为 JavaScript。

guaranteedShuffle($array){
    $isDifferent = false;
    while(!$isDifferent){
        $arrayCopy = $array;
        shuffle($arrayCopy);
        if($array !== $arrayCopy){
            $isDifferent = true;
        }
    }
    return $arrayCopy;
} 

用法:

$array = ['1','2']; 
$shuffled = guaranteedShuffle($array);
于 2017-03-02T16:53:10.970 回答
-1

您可以使用Fisher Yates Shuffle进行随机播放

function fisherYates ( myArray ) {
var i = myArray.length, j, tempi, tempj;
if ( i == 0 ) return false;
while ( --i ) {
 j = Math.floor( Math.random() * ( i + 1 ) );
 tempi = myArray[i];
 tempj = myArray[j];
 myArray[i] = tempj;
 myArray[j] = tempi;
}
}

请参阅此参考

于 2013-02-21T13:50:12.227 回答