JS создает массив с уникальными случайными числами - PullRequest
0 голосов
/ 06 января 2019

Полный код выглядит следующим образом, в идеале у нас есть 4 блока div, которые должны быть случайным образом заполнены случайными числами ansValue, один из них (rightAnsValue с его rightAnsId) уже готов и работает нормально, мне удалось сделать его уникальным по сравнению с другими (код без комментария). Но я столкнулся с проблемой создания других, уникальных, у меня в ящиках остаются одинаковые значения. В комментариях это один из способов, которым я пытался решить эту проблему, но я уверен, что есть гораздо более простое и разумное решение, которое действительно работает. Буду признателен, если вы поможете найти понятное решение этой проблемы. (П.С. Я видел подобные вопросы, но они либо слишком сложны, либо выполнены без JS.)

function createAnswers(){
    for(ansId=1; ansId<5; ansId++){
        if(ansId!=rightAnsId){
            for(i=1; i<10; i++){
                digitArray[i-1] = i;
            }
            genNewRandNum();

            // ansArray.length = 3;
            // ansArray.push(ansValue);
            // for(k=0; k<3; k++){
            //     if(ansArray[k] == ansArray[k+1] || ansArray[k] == ansArray[k+2]){
            //         genNewRandNum();
            //         ansArray[k] = ansValue;
            //     }else if(ansArray[k+1] == ansArray[k+2]){
            //         genNewRandNum();
            //         ansArray[k+1] = ansValue;
            //     }else{
            //         break;
            //     }
            // }

            if(ansValue!=rightAnsValue){
                document.getElementById("box" + ansId).innerHTML = ansValue;
            }else{
                genNewRandNum();
                document.getElementById("box" + ansId).innerHTML = ansValue;
            }
        }
    }
}

Способ генерации новых чисел:

function genNewRandNum(){
    rand1 = digitArray[Math.floor(Math.random() * digitArray.length)];
    rand2 = digitArray[Math.floor(Math.random() * digitArray.length)];
    ansValue = rand1 * rand2;
}

Ответы [ 2 ]

0 голосов
/ 06 января 2019

Самый простой способ перебора - использовать выборку «принять / отклонить». Вы можете сделать что-то вроде этого:

uniqueRandomNumbers = function(n, nextRandom)
{
  var nums = {}; var m = 0;

  while(m < n)
  {
    var r = nextRandom();

    if(! nums.hasOwnProperty(r))
    {
      nums[r] = true; m++;
    }
  }

  return Object.keys(nums);
}

Здесь я использую тот факт, что объекты js реализованы в виде хэш-карт для получения хэш-набора. (Это имеет обратную сторону преобразования чисел в строки, но если вы не планируете немедленно выполнять арифметику с ними, это не проблема.)

Чтобы получить четыре уникальных целых числа от 0 до 9, вы можете сделать что-то вроде:

uniqueRandomNumbers(4, function() { return Math.floor(Math.random() * 10); })

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

0 голосов
/ 06 января 2019

Замените ваш genNewRandNum () на приведенный ниже код. Я использовал IIFE, чтобы создать переменную замыкания ужеGeneratedNumbers, которая доступна внутри функции generateRandomNumber (), которая вернулась.

Таким образом, каждый раз, когда genNewRandNum () выполняется, он проверяет ужеGeneratedNumbers, чтобы убедиться, что он всегда возвращает уникальное значение от 1 до 9.

var genNewRandNum = (function(){
  var alreadyGeneratedNumbers = {};
  return function generateRandomNumber() {
    var min = Math.ceil(1),
      max = Math.floor(9);
      randomNumber = Math.floor(Math.random() * (max - min + 1)) + min;
    
    if(alreadyGeneratedNumbers[randomNumber]) {
      return generateRandomNumber();
    } else {
      alreadyGeneratedNumbers[randomNumber] = randomNumber;
      return randomNumber;
    }

  }
})();



console.log(genNewRandNum());
console.log(genNewRandNum());
console.log(genNewRandNum());
console.log(genNewRandNum());
console.log(genNewRandNum());
console.log(genNewRandNum());
console.log(genNewRandNum());
console.log(genNewRandNum());
console.log(genNewRandNum());

Примечание. Если вы вызываете genNewRandNum () в 10-й раз, он выдаст ошибку. Так что если у вас есть вариант использования, когда вам нужно будет сбросить его после того, как все числа от 1 до 9 будут возвращены, то вам нужно добавить код для обработки этого

...