在Javascript / PHP中随机播放没有重复的随机数

时间:2013-02-21 13:44:48

标签: 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()。这个东西有什么解决方案吗?

6 个答案:

答案 0 :(得分: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));

这可能对你有所帮助。

答案 1 :(得分: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];
}

效率最高,但保证将元素放在不相同的索引中。

答案 2 :(得分:1)

你可以使用Fisher-Yates-Shuffle的变体,它有偏见地随机选择被交换的元素,被称为Sattolo's algorithm

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;
}

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

答案 3 :(得分:0)

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

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

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()替换为:< / p>

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

,最后一个方法如下:

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

答案 4 :(得分:0)

我刚刚提出了以下代码,以解决我遇到的问题,有时我的随机洗牌阵列会以其原始顺序结束(是随机,或者不是随机?)。

它如何工作,它循环一个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);

答案 5 :(得分:-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;
}
}

See this reference