Подтвердить что ты не робот

Случайное число, которое не равно предыдущему числу

Мне нужно получить случайное число, но оно не должно быть равно предыдущему числу. Вот мой фрагмент кода. Но это не сработает.

function getNumber(){
  var min = 0;
  var max = 4;
  var i;
  i = Math.floor(Math.random() * (max - min)) + min;
  if (i=== i) {
    i = Math.floor(Math.random() * (max - min)) + min;
  }
  return i;
};

console.log(getNumber());
4b9b3361

Ответ 1

В этом ответе представлены три попытки

  • Простая версия с свойством функции getNumber, last, которая хранит последнее случайное значение.

  • Версия, которая использует замыкание над значениями min и max с повышением исключения, если max меньше min.

  • Версия, которая объединяет замыкание и идею сохранения всех случайных значений и использует их, как кажется подходящим.


One

Вы можете использовать свойство getNumber для хранения последнего номера и использовать цикл do ... while.

function getNumber() {
    var min = 0,
        max = 4,
        random;

    do {
        random = Math.floor(Math.random() * (max - min)) + min;
    } while (random === getNumber.last);
    getNumber.last = random;
    return random;
};

var i;
for (i = 0; i < 100; i++) {
    console.log(getNumber());
}
.as-console-wrapper { max-height: 100% !important; top: 0; }

Ответ 2

Следующий метод генерирует новое случайное число в диапазоне [min, max] и гарантирует, что это число отличается от предыдущего, без циклирования и без рекурсивных вызовов (Math.random() вызывается только один раз):

  • Если существует предыдущее число, уменьшите max на один
  • Создать новое случайное число в диапазоне
  • Если новый номер равен или больше предыдущего, добавьте один
    (Альтернатива: если новый номер равен предыдущему, установите его на max + 1)

Чтобы сохранить предыдущее число в закрытии, getNumber может быть создан в IIFE:

// getNumber generates a different random number in the inclusive range [0, 4]
var getNumber = (function() {
  var previous = NaN;
  return function() {
    var min = 0;
    var max = 4 + (!isNaN(previous) ? -1 : 0);
    var value = Math.floor(Math.random() * (max - min + 1)) + min;
    if (value >= previous) {
      value += 1;
    }
    previous = value;
    return value;
  };
})();

// Test: generate 100 numbers
for (var i = 0; i < 100; i++) {
  console.log(getNumber());
}
.as-console-wrapper {
  max-height: 100% !important;
  top: 0;
}

Ответ 3

Большинство ответов в этом потоке сложнее.

Вот краткий пример того, как я это сделаю:

function getNumber(){
    return (getNumber.number = Math.floor(Math.random() * (4 + 1))) === getNumber.lastNumber ? getNumber() : getNumber.lastNumber = getNumber.number;
}

console.log(getNumber()); // Generates a random number between 0 and 4

Пример в реальном времени: https://jsfiddle.net/menv0tur/3/

Ответ 4

Прежде всего функция должна сравниваться с предыдущим значением, теперь мы имеем только переменную i, которая сравнивается с самим собой. Чтобы быть уверенным, что у нас нет прежнего значения, нам нужно сделать цикл внутри (рекурсивный в моем решении), потому что single if statement не дает нам уверенности, что второй случайный будет не то же самое (есть шанс на это). Ваш набор чисел очень мал, поэтому вероятность столкновения высока, и вполне возможно, что цикл требует нескольких исполнений.

function getNumber(prev){
  var min = 0;
  var max = 4;
  var next;
  
  next = Math.floor(Math.random() * (max - min)) + min;
  
  if (next===prev) {
    console.log("--run recursion. Our next is ="+next); //log only for test case
    next = getNumber(prev); //recursive
  }
  
  return next;
};

//test 100 times
var num=0;
for ( var i=0; i<100; i++){
  num=getNumber(num);
  console.log(num);
}

Ответ 5

Удалите предыдущее значение из набора возможных значений с самого начала.

function getNumber(previous) {
  var numbers = [0, 1, 2, 3, 4];
  if (previous !== undefined) {
      numbers.splice(numbers.indexOf(previous), 1);
  }

  var min = 0;
  var max = numbers.length;
  var i;
  i = Math.floor(Math.random() * (max - min)) + min;

  return numbers[i];
};

//demonstration. No 2 in  a row the same
var random;
for (var i = 0; i < 100; i++) {
  random = getNumber(random);
  console.log(random);
}

Ответ 6

Вам понадобится переменная с большей областью действия, чем переменные, локальные для вашей функции getNumber. Попробуйте:

var j;
function getNumber(){
  var min = 0;
  var max = 4;
  var i = Math.floor(Math.random() * (max - min)) + min;
  if (j === i) {
    i = getNumber();
  }
  j = i;
  return i;
};

Ответ 7

Вы можете использовать реализацию шаблона @NinaScholz, где предыдущее значение сохраняется как свойство вызывающей функции, заменяя условную логику на увеличение или уменьшение текущего возвращаемого значения для цикла.

Если текущее значение равно ранее возвращенному значению, текущее значение изменяется во время текущего вызова функции, не используя цикл или рекурсию, перед возвратом измененного значения.

var t = 0;

function getNumber() {
  var min = 0,
    max = 4,
    i = Math.floor(Math.random() * (max - min)) + min;

  console.log(`getNumber calls: ${++t}, i: ${i}, this.j: ${this.j}`);

  if (isNaN(this.j) || this.j != i) {
    this.j = i;
    return this.j
  } else {

    if (this.j === i) {

      if (i - 1 < min || i + 1 < max) {
        this.j = i + 1;
        return this.j
      }

      if (i + 1 >= max || i - 1 === min) {
        this.j = i - 1;
        return this.j
      }

      this.j = Math.random() < Math.random() ? --i : ++i;
      return this.j

    }
  }
};

for (var len = 0; len < 100; len++) {
  console.log("random number: ", getNumber());
}

Ответ 8

Общее решение

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

Рабочая демонстрация

var getNumber = (function(){
  var min = 0;
  var max = 4;
  var last = -1;
  return function(){
    var current;
    do{
      // draw a random number from the range [min, max]
      current = Math.floor(Math.random() * (max + 1 - min)) + min;
    } while(current === last)
    return (last = current);
  }
})();

// generate a sequence of 100 numbers,
// see that they all differ from the last

for(var test = [], i = 0; i < 100; i++){
  test[i] = getNumber();
}
console.log(test);

Ответ 9

Это решение использует генераторы ES6 и избегает генерации случайных чисел, пока вы не найдете тот, который соответствует предусловию (два коррелированных числа должны быть разными).

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

function* genNumber(max = 4) {// Assuming non-repeating values from 0 to max
  let values = [...Array(max).keys()],
      indexes = [...Array(max).keys()],
      lastIndex,
      validIndexes;

  do {
    validIndexes = indexes.filter((x) => x !== lastIndex);
    lastIndex = validIndexes[Math.floor(Math.random() * validIndexes.length)];
    yield values[lastIndex];
  } while(true);
}

var gen = genNumber();
for(var i = 0; i < 100; i++) {
  console.log(gen.next().value);
}

Здесь fiddle в случае, если вы хотите проверить результат.

Ответ 10

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

// global variables
 tot_num = 10; // How many number want to generate?
 minimum = 0; // Lower limit
 maximum = 4; // upper limit
 gen_rand_numbers = []; // Store generated random number to prevent duplicate.

/*********** **This Function check duplicate number** ****************/
 function in_array(array, el) {
	for (var i = 0; i < array.length; i++) {
		if (array[i] == el) {
			return true;
		}
	}
	return false;
}

/*--- This Function generate Random Number ---*/
function getNumber(minimum, maximum) {
	var rand = Math.floor(Math.random() * (maximum - minimum + 1)) + minimum;
	if (gen_rand_numbers.length <= (maximum - minimum)) {
		if (!in_array(gen_rand_numbers, rand)) {
			gen_rand_numbers.push(rand);
			//alert(rand)
      console.log(rand);
			return rand;
		} else {
			return getNumber(minimum, maximum);
		}
	} else {
		alert('Final Random Number: ' + gen_rand_numbers);
	}

}

/*--- This Function call random number generator to get more than one random number ---*/

function how_many(tot_num) {
	for (var j = 0; j < tot_num; j++) {
		getNumber(minimum, maximum);
	}
	
}
<script src = "https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js" > </script>

	<input type = "button"	onclick = "how_many(4)" value = "Random Number" >

Ответ 11

Вы можете использовать расширенную реализацию линейного конгруэнтного генератора .

Линейный конгруэнтный генератор (LCG) является алгоритмом, который дает последовательность псевдо-рандомизированных чисел, вычисленных с разрывным кусочно-линейным уравнением.

Следующая функция возвращает посеянное случайное число в сочетании с минимальным и максимальным значением:

Math.seededRandom = function(seed, min, max) {
  max = max || 1;
  min = min || 0;

  // remove this for normal seeded randomization
  seed *= Math.random() * max;

  seed = (seed * 9301 + 49297) % 233280;
  let rnd = seed / 233280.0;

  return min + rnd * (max - min);
};

В вашем случае, поскольку вы никогда не хотите, чтобы новый номер был таким же, как и предыдущий, вы можете передать ранее сгенерированный номер в качестве семени.

Ниже приведен пример этого, который генерирует 100 случайных чисел:

Math.seededRandom = function(seed, min, max) {
  max = max || 1;
  min = min || 0;
  
  // remove this for normal seeded randomization
  seed *= Math.random() * max;
  
  seed = (seed * 9301 + 49297) % 233280;
  let rnd = seed / 233280.0;

  return min + rnd * (max - min);
};



let count = 0;
let randomNumbers = [];
let max = 10;
do {
  let seed = (randomNumbers[randomNumbers.length -1] || Math.random() * max);
  
  randomNumbers.push(Math.seededRandom(seed, 0, max));
  count++;
} while (count < 100)

console.log(randomNumbers);

Ответ 12

Веселый ответ, чтобы генерировать числа от 0 до 4 в одной строке:

console.log(Math.random().toString(5).substring(2).replace(/(.)\1+/g, '$1').split('').map(Number));

Ответ 13

function getNumber(){
    var min = 0;
    var max = 4;
    var i;
    i = Math.floor(Math.random() * (max - min)) + min;
    while(i==getNumber.last)
        i = Math.floor(Math.random() * (max - min)) + min;
    getNumber.last=i;
    return i;
};

console.log(getNumber());

Ответ 14

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

var prev_no = -10;

function getNumber(){
    var min = 0;
    var max = 4;
    var i;
    i = Math.floor(Math.random() * (max - min)) + min;
    while (i == prev_no) {
        i = Math.floor(Math.random() * (max - min)) + min;
        prev_no = i;
    }

    return i;
};

console.log(getNumber());

Ответ 15

Вы можете использовать Promise, Array.prototype.forEach(), setTimeout. Создайте и итерации массив, имеющий .length, установленный в max; используйте setTimeout в .forEach() обратном вызове с duration, чтобы установить случайное значение, чтобы вывести индекс массива в новый массив для неравномерного распределения индексов в новом массиве. Возврат разрешен Promise из getNumber функции, где Promise значение в .then() будет массивом .length max, имеющим случайный index от .forEach() обратный вызов как значения без повторяющихся записей.

function getNumber(max) {
  this.max = max;
  this.keys = [];
  this.arr = Array.from(Array(this.max));
  this.resolver = function getRandom(resolve) {
    this.arr.forEach(function each(_, index) {
      setTimeout(function timeout(g) {
        g.keys.push(index);
        if (g.keys.length === g.max) {
          resolve(g.keys)
        };
      }, Math.random() * Math.PI * 100, this);
    }, this)
  };
  this.promise = new Promise(this.resolver.bind(this));
}

var pre = document.querySelector("pre");

var random1 = new getNumber(4);
random1.promise.then(function(keys) {
  pre.textContent += keys.length + ":\n";
  keys.forEach(function(key) {
    pre.textContent += key + " ";
  })
});

var random2 = new getNumber(1000);
random2.promise.then(function(keys) {
  pre.textContent += "\n\n";
  pre.textContent += keys.length + ":\n";
  keys.forEach(function(key) {
    pre.textContent += key + " ";
  })
});
pre {
  white-space: pre-wrap;
  width: 75vw;
}
<pre></pre>

Ответ 16

Вы не можете достичь этого, если только вы не выполняете запрос базы данных, чтобы проверить наличие нового номера. Если существует, повторите процесс.

Существует архитектурная возможность создания уникального случайного числа - генерировать два случайных числа и комбинировать строки.

Например:

rand_num1 = rand(5);
rand_num2 = rand(4);

затем объединить rand_num1 и rand_num2, который больше похож на уникальный

Практический пример:

(23456)(2345)
(23458)(1290)
(12345)(2345)

Также увеличьте количество цифр, чтобы уменьшить повторение.