Произвольное перемещение случайных чисел без повторения в Javascript / PHP

Я просмотрел некоторые из ответов здесь, но это не похоже на то, что мне нужно, или я просто не знаю, как его применять.

Я не начал никаких кодов, и я только думаю о том, как это сделать, и я понятия не имею, как это сделать. Мне нужна твоя помощь.

Предположим, что у меня есть массив, который состоит из этих значений ниже

[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 () . Любое решение для этого?

Попробуй это,

 $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)); 

может это вам помочь.

То, что вы хотите сделать, – это добавить элементы из вашего массива в другой массив случайным образом, но для обеспечения того, чтобы элементы не находились в одной и той же индексированной позиции. Попробуй это:

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

Не самый эффективный, но гарантированный способ размещения элементов в одних и тех же индексах.

Вы можете использовать вариант Fisher-Yates-Shuffle, который предвзято произвольно выбирает замененный элемент и известен как алгоритм Саттоло :

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

Таким образом, каждый элемент гарантированно будет заменен и не появится в том же положении, что и раньше.

Это приводит к тому, что значения массива не повторяют предыдущую позицию для n shuffles (я использую половину размера массива как 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); } 

EDIT: если вы просто хотите, чтобы он не повторял предыдущую позицию, тогда make 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; } 

Я только что придумал следующий код, чтобы бороться с проблемой, с которой я столкнулся, где иногда мой случайный перетасованный массив окажется в его первоначальном порядке (был ли он слишком случайным или не случайным?).

Как это работает, он перебирает цикл while, пока переменная $ isDifferent не станет истинной, что может произойти только в том случае, если массивы не совпадают. Возможно, это может работать аналогично методу Фишера-Йейса, хотя, когда я это пробовал, я по-прежнему получал соответствующие массивы.

Это решение написано на PHP, но может быть легко преобразовано в JavaScript.

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

Применение:

 $array = ['1','2']; $shuffled = guaranteedShuffle($array); 

Вы можете перемешать с помощью 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; } } 

См. Эту ссылку