Как генерировать два разных случайных числа?
мне нужно сгенерировать два разных случайных числа, они не могут быть равны друг другу или третьему числу. Я пытался использовать много if, чтобы охватить все возможности, но, похоже, мои навыки алгоритма не так хороши.
может кто-нибудь помочь мне в этом?
var numberOne = Math.floor(Math.random() * 4);
var numberTwo = Math.floor(Math.random() * 4);
var numberThree = 3; // This number will not always be 3
if((numberOne == numberThree) && (numberOne + 1 < 3)) {
numberOne++;
} else if ((numberOne == numberThree) && (numberOne + 1 == 3)) {
numberOne = 0;
}
if ((numberOne == numberTwo) && (numberOne+1 < 3)) {
if (numberOne+1 < 3) {
numberOne++;
} else if(numberThree != 0) {
numberOne = 0;
}
}
это то, что у меня есть до сих пор, следующим шагом будет:
if (numberTwo == numberThree) {
(...)
}
правильно ли я мыслю? Примечание: генерируемые числа должны находиться между 0 и 3. Спасибо заранее.
8 ответов
Вы можете запустить while
цикл, пока все числа не будут разными.
// All numbers are equal
var numberOne = 3;
var numberTwo = 3;
var numberThree = 3;
// run this loop until numberOne is different than numberThree
do {
numberOne = Math.floor(Math.random() * 4);
} while(numberOne === numberThree);
// run this loop until numberTwo is different than numberThree and numberOne
do {
numberTwo = Math.floor(Math.random() * 4);
} while(numberTwo === numberThree || numberTwo === numberOne);
вот jsfiddle с вышеуказанным кодом, основанным на предложении @jfriend00 http://jsfiddle.net/x4g4kkwc/1.
вот оригинальная рабочая демонстрация:http://jsfiddle.net/x4g4kkwc/
вы можете создать массив случайных возможностей, а затем удалить элементы из этого массива по мере их использования, выбрав будущие случайные числа из оставшихся значений в массиве. Это позволяет избежать цикла, пытаясь найти значение, которое не соответствует предыдущим элементам.
function makeRandoms(notThis) {
var randoms = [0,1,2,3];
// faster way to remove an array item when you don't care about array order
function removeArrayItem(i) {
var val = randoms.pop();
if (i < randoms.length) {
randoms[i] = val;
}
}
function makeRandom() {
var rand = randoms[Math.floor(Math.random() * randoms.length)];
removeArrayItem(rand);
return rand;
}
// remove the notThis item from the array
if (notThis < randoms.length) {
removeArrayItem(notThis);
}
return {r1: makeRandom(), r2: makeRandom()};
}
рабочая демонстрация:http://jsfiddle.net/jfriend00/vhy6jxja/
FYI, этот метод обычно более эффективен, чем цикл, пока вы не получите что - то новое, когда вы просите случайным образом выберите большинство чисел в диапазоне, потому что это просто устраняет ранее использованные числа из случайного набора, поэтому ему не нужно снова и снова гадать, пока он не получит неиспользуемое значение.
эта версия минимизирует количество вызовов случайных, как вы сделали, но немного проще и не предвзято. В вашей версии есть шанс 2/4, что numberOne перейдет к 0, и шанс 1/4, если перейдет к 1 и 2. В моей версии есть равные шансы numberOne в конечном итоге как 0, 1 или 2).
i0 = Math.floor(Math.random() * 4); //one of the 4 numbers in [0, 4), namely 3
i1 = Math.floor(Math.random() * 3); //only 3 possibilities left now
i2 = Math.floor(Math.random() * 2); //only two possibilities left now
x0 = i0;
x1 = i1 + (i1 >= i0 ? 1 : 0);
x2 = i2 + (i2 >= i0 ? 1 : 0) + (i2 >= i1 : 1 : 0);
это особый случай упомянутой версии deceze для перетасовки массива, но когда у вас есть только два числа
Я не уверен, что вы пытаетесь сделать (или на самом деле, почему ваш код настолько сложен, что я понял). Возможно, это не самый оптимизированный код, но вот моя попытка:
var n3 = 3;
var n2 = Math.floor(Math.random() * 4);
var n1 = Math.floor(Math.random() * 4);
while(n1 == n3)
{
n1 = Math.floor(Math.random() * 4);
}
while (n2 == n1 || n2 == n3)
{
n2 = Math.floor(Math.random() * 4);
}
EDIT: черт, слишком поздно ^^
var rangeTo = 4;
var uniqueID = (function () {
var id, cache = [];
return function () {
id = Math.floor((Math.random() * (new Date).getTime()) % rangeTo);
var cacheLength = cache.length;
if (cacheLength === rangeTo) {
throw new Error("max random error");
};
var i = 0
while (i < cacheLength) {
if (cache[i] === id) {
i = 0;
id = Math.floor((Math.random() * (new Date).getTime()) % rangeTo);
}
else {
i++;
}
}
cache.push(id);
return id;
};
})();
var n = 4; //to get two random numbers between 0 and 3
var n3 = 2; //for example
var n1 = Math.floor(Math.random(n-1));
var n2 = Math.floor(Math.random(n-2));
if(n1 >= n3) {
n1++;
if(n2 >= n3)
n2++;
if(n2 >= n1)
n2++;
} else {
if(n2 >= n1)
n2++;
if(n2 >= n3)
n2++;
}
вам нужно сравнить n2
минимум n1
и n3
во-первых, чтобы убедиться, что у вас нет равенства:
предположим n1=1
и n3=2
. Если вы получите n2=1
и сравните его сначала с n3
, вы не увеличите n2
на первом шаге. На втором этапе вы бы увеличили его с n2 >= n1
. В конце концов, n2 = 2 = n3
.
этот алгоритм гарантирует равномерное распределение, и вы звоните только дважды Math.random()
.
имейте в виду, что спина к спине вызывает Math.random()
вызывает ошибка в chrome как указано здесь, поэтому измените любой из других ответов, позвонив safeRand()
ниже.:
function safeRand() {
Math.random();
return Math.random();
}
Это все еще не идеально, но значительно уменьшает корреляции, так как каждый дополнительный, отброшенный вызов Math.random()
будет.
Как правило, в псевдо-коде я делаю:
var nbr1 = random()
var nbr2 = random()
while (nbr1 == nbr2) {
nbr2 = random();
}
таким образом, вы получите два разных случайных чисел. С дополнительным условием вы можете сделать их отличными от другого (3-го) числа.