Как я могу оптимизировать эту длинную строку утверждений "если"?
Итак, я делаю кликерную игру, используя Javascript, и я столкнулся с тем, что мне нужно было сделать ЛОТ, и я говорю о 300 заявлениях if. Я выполнил всю чрезвычайно утомительную работу и запустил свою игру.
Чтобы показать вам проблему, мне нужно показать свою игру. В общем, каждый раз, когда я нажимаю на кнопку, обновляется одно из десяти изображений.
Дело в том, что я сделал тонны утверждений if для каждого номера и для каждого материала, который вы можете собрать.
Мне было интересно, есть ли способ избавиться от всех этих выражений if и заставить игру работать нормально, или есть способ ее оптимизировать.
Код: JSFiddle Большая часть кода выглядит так:
if (A == 18) {
document.getElementById("A1").src = "images/blocks/2A.png";
document.getElementById("A2").src = "images/blocks/2A.png";
document.getElementById("A3").src = "images/blocks/2A.png";
document.getElementById("A4").src = "images/blocks/2A.png";
document.getElementById("A5").src = "images/blocks/2A.png";
document.getElementById("A6").src = "images/blocks/2A.png";
document.getElementById("A7").src = "images/blocks/2A.png";
document.getElementById("A8").src = "images/blocks/2A.png";
document.getElementById("A9").src = "images/blocks/1A.png";
document.getElementById("A10").src = "images/blocks/1A.png";
}
Если вам нужна ссылка на реальную игру, дайте мне знать, так как у JSFiddle нет моих картинок.
5 ответов
Как насчет наличия массива правил что-то вроде
const rules = [
{ rule: 18, imagePaths : [ {A1: "2A.png" }...{A10: "1A.png" } ]},
{ rule: 19 , imagePaths:[....] }
]
а затем, основываясь на номере правила, прочитайте imagePaths из правил и установите его соответствующим образом. т. е. если выбрано значение 18, получить правила на основе 18 из массива правил, а затем выполнить цикл imagePaths
и установите src на основе значения в правилах.
Если вы используете jQuery, вы можете попробовать что-то вроде этого:
if (A == 18) {
$('[id^=A]').each(function() {
$(this).attr("src", "images/blocks/2A.png");
});
$("#A9").attr("src", "images/blocks/1A.png");
$("#A10").attr("src", "images/blocks/1A.png");
}
Это работает, хватая каждый img
который имеет идентификатор, начинающийся с "А", а затем добавляя этот конкретный src
атрибут в конце.
И для двух уникальных, он меняет их, как только это будет сделано.
Я знаю, что это точно не решает if
Задача оператора, однако, значительно сократит ваш код:-)
Вы можете использовать цикл for для установки A+i, но я предлагаю вам установить тот же класс для dom с тем же содержимым. Вы можете использовать селекторы getElementsByClass или jQuery, а затем установить пакетный src.
function changeSrc(){
$(".type1").attr("src", "https://stackru.com/images/60f8c1fc53707de7ff13a2fee7902c3f6181dd2f.jpg?s=32&g=1");
}
.type1 {display:block;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<img class="type1" src="https://stackru.com/images/15c96dbeac35709b26ca375ff8cea25f9531aaf6.jpg?s=48&g=1"/>
<img class="type1" src="https://stackru.com/images/15c96dbeac35709b26ca375ff8cea25f9531aaf6.jpg?s=48&g=1"/>
<img class="type1" src="https://stackru.com/images/15c96dbeac35709b26ca375ff8cea25f9531aaf6.jpg?s=48&g=1"/>
<img class="type1" src="https://stackru.com/images/15c96dbeac35709b26ca375ff8cea25f9531aaf6.jpg?s=48&g=1"/>
<img class="type1" src="https://stackru.com/images/15c96dbeac35709b26ca375ff8cea25f9531aaf6.jpg?s=48&g=1"/>
<button onclick="changeSrc()">chang src</button>
Единственная переменная у вас есть счетчик. Буквально все остальное можно напрямую рассчитать по этому счетчику, если вы только запишите правила.
Правила таковы,
Значения сечений A, B и C
Вы хотите создать числовые диапазоны с метками A, B и C, каждый из которых имеет значение от 0 до 99 и представляет другой раздел вашего счетчика, например:
123456
CCBBAA, i.e. A = 56, B = 34, C = 12
8921
CCBBAA, i.e. A = 21, B = 89, C = 0
Это можно сделать, равномерно разделив число на степень 100 и вычислив остаток (по модулю) до 100:
(123456 DIV 100^0) MOD 100 = 56
(123456 DIV 100^1) MOD 100 = 34
(123456 DIV 100^2) MOD 100 = 12
В JS целочисленное деление может выполняться округлением вниз. Math.floor(140 / 100)
не 1.4, а 1. Операция MOD выполняется оператором%, а операция питания - Math.pow()
функция. Таким образом, выше становится:
Math.floor(123456 / Math.pow(100, 0)) % 100 // = 56
Math.floor(123456 / Math.pow(100, 1)) % 100 // = 34
Math.floor(123456 / Math.pow(100, 2)) % 100 // = 12
Это значения ваших секций A, B и C, напрямую полученные из значения вашего счетчика.
Десять изображений на раздел
Вы хотите отобразить каждый из этих разделов с десятью изображениями. Их имена варьируются от "0X" до "10X", где "X" - соответствующая буква раздела.
Предполагая, что значение сечения равно 37, вы хотите, чтобы первые 7 изображений были "4X", а последние 3 "3X".
Опять же, мы можем получить имя изображения непосредственно из значения раздела. Давайте разберем 37 по целочисленному делению и по модулю на 3 и 7:
div = Math.floor(value / 10); // 37 => 3
rem = value % 10; // 37 => 7
Теперь имя изображения зависит от того, каким изображением мы манипулируем. Со счетчиком k
от 0 до 9 мы можем решить, должно ли имя изображения начинаться с 4 или 3.
imageName = (k < rem ? div + 1 : div) + letter;
Для любого k
меньше 7 мы получаем "4X", остальные получают "3X".
В коде это выглядит так:
var total = 0,
letters = ['A', 'B', 'C'];
function add() {
total++;
showState();
}
function showState() {
var letter, range, value, imageName, div, rem, i, k;
for (i = 0; i < 3; i++) {
letter = letters[i]; // "A", "B", "C"
range = Math.pow(100, i); // 1, 100, 10000
value = Math.floor(total / range) % 100; // 0 .. 99
document.getElementById(letter + "_Check").innerHTML = letter + ": " + value;
for (k = 0; k < 10; k++) {
div = Math.floor(value / 10); // 37 => 3
rem = value % 10; // 37 => 7
imageName = (k < rem ? div + 1 : div) + letter;
elem = document.getElementById(letter + (k + 1));
elem.src = "images/blocks/" + imageName + ".png";
}
}
}
Это весь код, который вам нужен, и ни одна строка не вставляется в копию.
Вот скрипка: https://jsfiddle.net/4kr2xwyq/2/
Упражнение: узнайте, можете ли вы полностью заменить изображения HTML/CSS (такие вещи, как гистограммы очень легко сделать в HTML, цвета и размеры элементов можно рассчитать и изменить на лету) или холстом. В конце концов, это может быть легче сделать, чем поддерживать десятки статических файлов изображений.
Все зависит от того, что вы после рефакторинга. Вы говорите, что имеете много операторов If, если они сравнивают одну и ту же переменную A, тогда можно использовать оператор switch, например:
switch (A)
{
case 18:
document.getElementById("A1").src = "images/blocks/2A.png";
document.getElementById("A2").src = "images/blocks/2A.png";
document.getElementById("A3").src = "images/blocks/2A.png";
document.getElementById("A4").src = "images/blocks/2A.png";
document.getElementById("A5").src = "images/blocks/2A.png";
document.getElementById("A6").src = "images/blocks/2A.png";
document.getElementById("A7").src = "images/blocks/2A.png";
document.getElementById("A8").src = "images/blocks/2A.png";
document.getElementById("A9").src = "images/blocks/1A.png";
document.getElementById("A10").src = "images/blocks/1A.png";
break;
case 19:
document.getElementById("A1").src = "images/blocks/2A.png";
document.getElementById("A2").src = "images/blocks/2A.png";
document.getElementById("A3").src = "images/blocks/2A.png";
etc...
break;
default:
document.getElementById("A1").src = "images/blocks/2A.png";
break;
}
Похоже, вы захотите создать функцию, которая передает элемент ID и возвращает строку для изображения в качестве второго рефакторинга.