#javascript #random #html-table #infinite-loop #innerhtml
#javascript #Случайный #html-таблица #бесконечный цикл #innerhtml
Вопрос:
function randomNumber(){
var value;
var flag = false;
var tds = document.querySelectorAll('td');
do{
value = Math.round(Math.random() * (26 - 1) 1);
for(var t = 0; t < tds.length; t ){
if(tds[t].innerHTML == value)
flag = true;
}
if(!flag){
return value;
}
}while(flag == true)
}
Эта функция возвращает случайное число для innerHTML нового td. В случае, если есть другие td с тем же номером, который генерирует этот код, цикл начинается снова. Если сгенерированное число уникально, я добавляю его в innerHTML нового td. Но я даже не могу загрузить страницу, так как я попадаю в бесконечный цикл, но как бы я ни старался, я не мог заметить проблему в логике этого кода.
Комментарии:
1. Какое условие следует установить
flag
как false ?2. Вопрос: Почему моя страница попадает в бесконечный цикл? Ответ: Вероятно, потому, что «значение», по-видимому, всегда равно «tds [t].innerHTML», а флаг никогда не остается «ложным». ПРЕДЛОЖЕНИЕ: пройдите по коду в отладчике (например, Chrome Developer Tools) и посмотрите на «значение» по мере выполнения цикла.
Ответ №1:
Как только ваш цикл найдет случай, для которого tds[t].innerHTML == value
он установлен flag
true
— на этом этапе вы никогда не сможете завершить цикл, потому что нигде вы не проверяете случай, для которого вы можете установить flag
значение false
, поэтому ваше условие цикла всегда будет истинным.
Вот аналогичный пример, который иллюстрирует это с помощью массива. Вы можете видеть, что иногда он добавляет числа в массив (в случае, когда он находит новое значение), но в других случаях цикл достигает 5000 итераций и завершается (потому что он никогда не находит новое значение), и в этом случае он добавляет undefined
в массив, поскольку функция ничего не вернула.
const arr = []
function randomNumber(){
var value;
var flag = false;
var tds = arr
var iterations = 0
do {
value = Math.round(Math.random() * (26 - 1) 1);
for(var t = 0; t < tds.length; t ){
if(tds.includes(value))
flag = true;
}
if(!flag){
return value;
}
iterations = 1
console.log(iterations)
} while(flag == true amp;amp; iterations < 5000)
}
for (let i = 0;i<20;i =1) {
arr.push(randomNumber())
}
console.log(arr)
Комментарии:
1. Вы получили
arr
доступ из функции in и out — не очень хорошо иметь глобальные переменные — вы действительно не должны писать такой код. Также — почему вы повторяете 5000 раз, если, например, все 26 идентификаторов уже используются? Вы потеряете более 4800 итераций, когда вы могли бы просто проверить, есть ли у вашей функции хотя бы небольшой шанс вернуть все, что она должна2. Отмеченные моменты — это пример, призванный проиллюстрировать принципы и показать, как продолжались итерации, а не реализация наилучшего практического решения.
3. Тем не менее, если бы вы получили это в своем коде, и этот код был запущен в производство — это было бы очень плохо
Ответ №2:
В тот момент, когда ваша функция хотя бы один раз установит значение flag
true, оно закончится — оно больше никогда не устанавливает его в false. Чтобы исправить это, я добавил одну строку кода.
function randomNumber(){
var value;
var flag = false;
var tds = document.querySelectorAll('td');
do {
flag = false; // this line i added
value = Math.round(Math.random() * (26 - 1) 1);
for(var t = 0; t < tds.length; t ){
if(tds[t].innerHTML == value)
flag = true;
}
if(!flag){
return value;
}
}while(flag == true)
}
Я также напишу для вас немного более эффективный код
function randomNumber(){
var value;
var found = false;
var tds = document.querySelectorAll('td');
var existingIds = [];
tds.forEach(td => existingIds.push(td.innerHHML)); // fill up the ids
do {
value = Math.round(Math.random() * (26 - 1) 1); // this line would make problems (comment below)
if (existingIds.indexOf(value) === -1) found = true; // check if value can be found in existing ids and if found - set dount to true (you can also return from here, but i would rather user break (if there was more code after this line, than use retur in the middle of any loop;
} while(found === false)
return value;
}
Комментарий к строке со случайным:
- random() возвращает число от 0 до 1
- как вы это написали — это значение будет случайным числом от 1 до 26 (только это значение).
- если все значения уже использованы, то наш цикл не будет заканчиваться (мы никогда не смогли бы найти значение от 1 до 26, которое не используется, когда все значения от 1 до 26 уже используются.
Что можно сделать
- В этом случае вы можете добавить некоторый счетчик (как это сделал @Ben) и выйти из цикла.
- Или вы можете увеличить число 26 до гораздо большего
- Вы можете использовать последовательные числа (получить все, взять максимальное, добавить 1 и вернуть это как новое число)
Вы, конечно, можете найти другие способы противостоять этому
Комментарии:
1. Вау, я просто немного раздражен, что все так просто. Я потратил на это около 30 минут. Большое спасибо.
2. Нет проблем, это происходит, когда вы только начинаете свое приключение с программированием / языком
3. @Дмитрий Уткин — Пожалуйста, ознакомьтесь с хорошим отладчиком и приобретите привычку пошагово выполнять свой код.