在Javascript/PHP中不重复地洗牌随机数

在Javascript/PHP中不重复地洗牌随机数,php,javascript,arrays,shuffle,Php,Javascript,Arrays,Shuffle,我在这里搜索了一些答案,但它似乎不是我需要的东西,或者我只是不知道如何应用它 我还没有开始编写任何代码,我只是在想怎么做,我不知道怎么做。我需要你们的帮助 让我们假设我有一个数组,它由下面的这些值组成 [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()。有没

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

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

让我们假设我有一个数组,它由下面的这些值组成

[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()。有没有解决这个问题的方法?

这使得数组的值在n次洗牌时不会重复前面的任何位置(我使用数组大小的一半作为n,然后重新启动禁止索引)。最后,a修改了此版本,使其不重复当前位置

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

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);
}
编辑:如果您只是想防止它重复上一个位置,那么请使
不可用\u索引
保留它所处的最后一个位置,并将
do{…}while()替换为:

do{
    newIndex = Math.floor(Math.random()*arrayLen);
}while(newIndex != value.unavailable_indexes)
最后一种方法如下所示:

$.each(numberArray, function(index, value){
   value.unavailable_indexes = index;
}
您可以使用

试试这个

$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));
$numbers=array();
做{
$可能=兰特(1,15);
如果(!isset($number[$mably])){
$numbers[$problem]=true;
}
}而(计数($number)<15);
打印(数组键($number));

这可能会对您有所帮助。

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

$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];
}
$array=[1,2,3,4,5,6,7,8,9];
$new=array();
对于($i=0;$i<$array.length;$i++){
$rand=$i;
做{
$rand=Math.floor(Math.random()*($array.length+1));
}而($rand==$i | |数组_key_存在($rand,$new))
//检查新位置是否不等于当前索引
//而且它不包含其他元素
$new[$rand]=$array[i];
}

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

您可以使用的变体不随机选择交换的元素,称为:


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

我刚刚提出了以下代码,以解决我遇到的一个问题:有时随机洗牌的数组会以其原始顺序结束(是太随机,还是不够随机?)

它是如何工作的,它在一个while循环中循环,直到$isDifferent变量变为true,这只能发生在数组不匹配的情况下。这可能与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);

是否要创建所有可能的组合?如果不只是洗牌数组,请将其与已洗牌的每个数组进行比较。在php中,您可以使用函数
shuffle(&$array)
。传递一个数组-它将为您洗牌。您不能保证恒定的不重复,但在随后的两次调用中不太可能得到重复的结果。您还可以将数组拆分为较小的数组,将其洗牌,然后以随机顺序从较小的数组中重新创建较大的数组。所以你最终得到[2,3,1][6,5,4][8,9,7],然后可能是[6,5,4][2,3,1][8,9,7],当合并后变成:[6,5,4,2,3,1,8,9,7],所以你不希望数字在相同的位置重复多少次迭代/萨福克?@Bergi,据我所知,他不希望每个数字重复n次萨福克的相同/最后位置。所以它不是一个复制品实际上,它效率很低,而且有一个更优雅的解决方案来确保
i!=j
No。这可能是最后一个结果。@joe:不太可能(或者更确切地说,根据算法,不可能,只要数组有多个元素)。你能演示一下你的代码吗(比如小提琴)?@joe:你可能已经在重复记录同一个数组了。Try(
shufflearlay
尚未更改)它会给出相同的结果。第二个日志实际上是相同的[1,2,3],所以位置是重复的。@joe当然第二个日志可以与原始输入相同,只是保证在所有位置上都与第一个日志不同。duh:D我刚刚意识到问题出在哪里。它返回相同的数组(修改原来的数组),因此下一个调用将开始洗牌类似于[3,1,2]的内容,它们可以返回[1,2,3],因为它们不在相同的位置:)
guaranteedShuffle($array){
    $isDifferent = false;
    while(!$isDifferent){
        $arrayCopy = $array;
        shuffle($arrayCopy);
        if($array !== $arrayCopy){
            $isDifferent = true;
        }
    }
    return $arrayCopy;
} 
$array = ['1','2']; 
$shuffled = guaranteedShuffle($array);