У меня возникла проблема, чтобы получить массив с номерами от 1 до 16 случайным образом без повторения. Я сделал массив num для помещения чисел из функции createNum .

Функция createNum имеет цикл for, который получает числа от 1 до 16, пока оператор if не вставит 16 чисел в массив num .

В конце я запускаю createNum () и отображаю числа в сети. Пока я делаю этот код, он иногда работал, но теперь он не работает.

Может кто-нибудь указать, где я сделал ошибки?

let num = []; function createNum () { for (i = 0; i {amp}lt;= 15;) { let numGen = Math.floor(Math.random() * 15)   1; if (!num.includes(numGen)) { num.push(numGen); i  ; }; }; } console.log(createNum()); document.getElementById("selectedNumbersShownHere").innerHTML = num; console.log(num); 

Кей. T

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

Правила поведения

,

Это потому, что Math.random() никогда не возвращает 1, поэтому в конце Math.floor(Math.random() * 15) вернет максимум 14 и добавив его к 1, вы получите максимум 15. Используйте Math.ceil вместо Math.floor то есть

 let num = []; function createNum () { for (i = 0; i {amp}lt;=15;) { let numGen = Math.ceil(Math.random() * 16); console.log(numGen) if (!num.includes(numGen)) { num.push(numGen); i  ; }; }; } console.log(createNum()); document.getElementById("selectedNumbersShownHere").innerHTML = num; console.log(num); 

Надеюсь, это поможет!

for (i = 0; i {amp}lt;= 15;) генерирует 16 чисел, но Math.floor(Math.random() * 15) 1 имеет только 15 возможных значений (1 ~ 15).

Функция shuffle рекомендуется. Ваша функция будет медленной, если вы генерируете перемешанный массив большого размера.

Как я могу перемешать массив?

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

Плюс:
Ваша формула неверна : let numGen = Math.floor(Math.random() * 15) 1;
и должно быть …………….: let numGen = Math.floor(Math.random() * 16) 1; значение 16

см ={amp}gt; Генерация случайных целых чисел в JavaScript в определенном диапазоне?

сделай это:

 function createNum() { let num =[], lastOne =136; // 136 = 1  2  3   ...  16 for (;;) { let numGen = Math.floor(Math.random() *16)  1; if (!num.includes(numGen)) { lastOne -= numGen; if (num.push(numGen){amp}gt;14) break; } } num.push(lastOne); // add the missing one (optimizing) return num; } let unOrdered_16_vals = createNum(); /* document.getElementById("selectedNumbersShownHere").textContent = unOrdered_16_vals.join(''); */ console.log( JSON.stringify( unOrdered_16_vals ), 'length=', unOrdered_16_vals.length ); console.log( 'in order = ', JSON.stringify( unOrdered_16_vals.sort((a,b)={amp}gt;ab) ) ); 

примечание: метод push() добавляет один или несколько элементов в конец массива и возвращает новую длину массива.

Проблема в вашем коде в том, что вы ищете 16 различных чисел из 15 возможных значений.

Причина этого заключается в том, что Math.floor(Math.random() * 15) 1; будет возвращать значения только от 1 до 15, но ваш цикл будет работать до тех пор, пока у вас не будет 16 уникальных значений, поэтому вы входите в бесконечный цикл.

То, что вы в основном пытаетесь достичь — это случайное перемешивание массива со значениями от 1 до 16.

Одним из распространенных решений с хорошей производительностью ( O(n) ) является так называемое перемешивание по Фишеру-Йейтсу . Вот код, который отвечает вашим требованиям на основе реализации Майка Бостока :

 function shuffle(array) { let m = array.length, t, i; while (m) { i = Math.floor(Math.random() * m--); t = array[m]; array[m] = array[i]; array[i] = t; } return array; } // create array with values from 1 to 16 const array = Array(16).fill().map((_, i) ={amp}gt; i   1); // shuffle const shuffled = shuffle(array); console.log(shuffled); 

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


(1) В теории вероятностей это называется проблемой коллекционера купонов . Для значения n, равного 16, в среднем необходимо сделать 54 вызова для сбора всех 16 значений.

Попробуйте вот так:

  let num = []; function createNum () { for (i = 0; num.length {amp}lt;= 17; i  ) { let numGen = Math.floor(Math.random() * 16)   1; if (!num.includes(numGen)) { num.push(numGen); }; }; } console.log(createNum()); document.getElementById("selectedNumbersShownHere").innerHTML = num; console.log(num); 

Пожалуйста, найдите рабочую демонстрацию здесь

 This is an infinite loop error. Because your loop variable "i" is always less than or equal to 15. and your i   is inside the if statement. You can achieve it in multiple ways. Below is one sample. let num = []; function createNum () { for (i = 0; i {amp}lt;= 15;) { let numGen = Math.floor(Math.random() * 15)   1; if (!num.includes(numGen)) { num.push(numGen); }; i  ; }; } console.log(createNum()); document.getElementById("selectedNumbersShownHere").innerHTML = num; console.log(num); 

извините, я «увлечен» этим вопросом и не могу удержаться от того, чтобы представить второй ответ, который ИМХО: лучший!

 function createNum () { let num = [] for (let len=0;len{amp}lt;16;) { let numGen = Math.ceil(Math.random() * 16) if (!num.includes(numGen)) { len = num.push(numGen) } } return num } let unOrdered = createNum(); console.log( JSON.stringify( unOrdered ) ); /* document.getElementById("selectedNumbersShownHere").textContent = unOrdered_16_vals.join(''); */