2016-09-04 2 views
1

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

function randomize(arr) { 
      return arr[Math.floor(Math.random()*arr.length)]; 
     } 

oracleImg = []; 
      for (var i=1;i<=6;i++) { 
      oracleImg.push(i); 
     } 

randOracleImg = randomize(oracleImg); 

Я пробовал следующее, но это не всегда дает мне отличный от последнего числа.

function randomize(arr) { 
    var arr = Math.floor(Math.random()*arr.length); 
    if(arr == this.lastSelected) { 
      randomize(); 
     } 
     else { 
      this.lastSelected = arr; 
      return arr; 
     } 
} 

Как это исправить?

+6

Если он всегда отличается от предыдущего номера, то он не является случайным. – stark

+0

ОДОБРЕННО, что число будет таким же, как и у второго, или является реальным требованием для обработки всего массива в случайном порядке? – nnnnnn

+0

Совсем нет. Вы выбираете случайное число из [0, arr.length). – Li357

ответ

1

Рекурсивный вызов вашей существующей функции randomize() не имеет смысла, потому что вы не передаете ему аргумент arr, и вы ничего не делаете с его возвращаемым значением. Эта линия должна быть:

return randomize(arr); 

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

Обратите внимание, что я также добавил тест, чтобы убедиться, что если массив имеет только один элемент, мы немедленно возвращаем этот элемент, потому что в этом случае каждый раз невозможно выбрать другой элемент. (Функция возвращает undefined если массив пуст.)

function randomize(arr) { 
 
    if (arr.length < 2) return arr[0]; 
 
    var num = Math.floor(Math.random()*arr.length); 
 
    if(num == this.lastSelected) { 
 
     return randomize(arr); 
 
    } else { 
 
     this.lastSelected = num; 
 
     return arr[num]; 
 
    } 
 
} 
 

 
document.querySelector("button").addEventListener("click", function() { 
 
    console.log(randomize(["a","b","c","d"])); 
 
});
<button>Test</button>

Обратите внимание, что, казалось, исходная функция будет возвращающей массив случайной индекса, но код, показанный в моем ответе возвращает случайный массив элемент.

Обратите внимание, что способ, которым вы вызываете свою функцию, означает, что внутри функции this есть окно - не уверен, что это то, что вы намеревались; он работает, но в основном lastSelected является глобальной переменной.

Учитывая, что я не намерен создавать глобальные переменные бесполезно, вот альтернативная реализация без глобальных переменных и без рекурсии, потому что, по моему мнению, простой цикл while является более семантическим способом реализации концепции «продолжайте пытаться до х бывает ":

var randomize = function() { 
 
    var lastSelected, num; 
 
    return function randomize(arr) { 
 
     if (arr.length < 2) return arr[0]; 
 
     while (lastSelected === (num = Math.floor(Math.random()*arr.length))); 
 
     lastSelected = num; 
 
     return arr[num]; 
 
    }; 
 
}(); 
 

 
document.querySelector("button").addEventListener("click", function() { 
 
    console.log(randomize(["a","b","c","d"])); 
 
});
<button>Test</button>

+0

Они ищут, чтобы вернуть элемент в массиве, а не в индекс. Поэтому строка 7 должна быть «return arr [num];». – Feathercrown

+0

@Feathercrown - правда. Я ответил на это в своем ответе. Хотя, глядя на дополнительный код, который теперь добавлен в вопрос, массив кажется избыточным, потому что все, что он содержит, это числа от 1 до 6, так почему бы просто не генерировать случайные числа в этом диапазоне, а не использовать массив? – nnnnnn

+0

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

1

Ниже код не только пример, он будет генерировать 99 номеров и все будет уникальным и случайным (Диапазон 0-1000), логика проста просто добавьте случайное число во временном массиве и сравнить новый случайный, если он уже сгенерирован или нет.

var tempArray = []; 
 
var i=0; 
 
while (i != 99) { 
 
    var random = Math.floor((Math.random() * 999) + 0); 
 
    if (tempArray.indexOf(random)==-1) { 
 
     tempArray.push(random); 
 
     i++; 
 
    } else { 
 
    continue; 
 
    } 
 
} 
 
console.log(tempArray);

+0

Перечитайте вопрос. Он просто хочет, чтобы каждый номер отличался от предыдущего **, а не ** всех ** предыдущих. –

1

Если вы хотите, чтобы всегда возвращать другое число из массива, то не рандомизации, перемешайте вместо этого! *

Простейшим справедливо (истинно случайный) алгоритм тасования Алгоритм Фишера-Йейта. Не делайте то же самое mistake Microsoft did and try to abuse .sort() to implement a shuffle.Просто реализовать Fisher-Yates (otherwise known as the Knuth shuffle):

// Fisher-Yates shuffle: 
// Note: This function shuffles in-place, if you don't 
//  want the original array to change then pass a copy 
//  using [].slice() 
function shuffle (theArray) { 
    var tmp; 
    for (var i=0; i<theArray.length;i++) { 
     // Generate random index into the array: 
     var j = Math.floor(Math.random()*theArray.length); 

     // Swap current item with random item: 
     tmp = theArray[i]; 
     theArray[j] = theArray[i]; 
     theArray[i] = tmp; 
    } 
    return theArray; 
} 

Так просто сделать:

shuffledOracleImg = shuffle(oracleImg.slice()); 

var i=0; 

randOracleImg = shuffledOracleImg[i++]; // just get the next image 
             // to get a random image 

Как вы хотите обрабатывать кончаются изображений до вас. Медиаплееры, такие как iTunes или музыкальный проигрыватель на iPhone, iPad и iPod, предоставляют пользователям возможность прекратить играть или повторять с самого начала. Некоторое программное обеспечение для карточных игр перестановит и начнет снова.

* примечание: один из моих домашних животных - это программное обеспечение для музыкального плеера, которое рандомизируется вместо тасования. Randomize - это именно то, что нужно сделать, потому что 1. в некоторых реализациях не проверяется, совпадает ли следующая песня с текущей песней, чтобы вы дважды воспроизводили песню (чего вы, похоже, хотите избежать) и 2. некоторые песни заканчиваются НИКОГДА не играя. Перемешивание и воспроизведение перетасованного плейлиста от начала до конца позволяет избежать обеих проблем. Производители CD-плееров правильно поняли. Разработчики MP3-плееров, как правило, ошибаются.

+0

Спасибо, я люблю этот ответ. Очень просто и логично. –

1

вот версия, которая обеспечит случайное число, которое всегда отличается от последнего. кроме того, вы можете управлять максимальным и минимальным значением генерируемого случайного значения. значения по умолчанию: max: 100 и min: 1

var randomize = (function() { 
    var last; 
    return function randomize(min, max) { 
     max = typeof max != 'number' ? 100 : max; 
     min = typeof min != 'number' ? 1 : min; 

     var random = Math.floor(Math.random() * (max - min)) + min; 
     if (random == last) { 
      return randomize(min, max); 
     } 

     last = random; 
     return random; 
    }; 
})(); 
+0

Спасибо суфийский –

Смежные вопросы