У кликера появятся ограничения и цель: сбор тратит энергию, улучшение стоит 10 кристаллов и покупается один раз, а 20 кристаллов завершают партию. Цвет кнопки будет лишь подсказкой; каждое правило проверим в JavaScript.
Попробуй правила прямо здесь: потрать десять единиц энергии, купи улучшение и отдохни. Сила станет 2; ещё десять сборов дадут 20 очков и победу. Ниже разберём проверки, которые разрешают и запрещают действия.
Для этого урока возьми final/ урока о DOM, функциях и событиях. Это start/ нынешнего комплекта. Ты уже умеешь объявить функцию, изменить число и вызвать render().
Открыть эту версию в отдельной вкладке
Выбирай стартовую версию, промежуточный этап или финал в просмотрщике. Во вкладке «Инструкция» — как запустить проект и чем отличаются версии. Решения самостоятельных заданий открывай после своей попытки.
Скачать ZIPРаспакуй архив целиком. У каждой версии своя папка с index.html, style.css и game.js. Открывай HTML внутри выбранной папки двойным щелчком; после правки сохраняй файл и обновляй браузер. Установка Node.js, аккаунт и сервер здесь не нужны. CSS уже знаком по первому модулю и дан как готовое оформление.
Если энергии нет — прекращаем действие
В game.js замени только handleGather:
function handleGather() {
if (energy <= 0) {
return;
}
score = score + clickPower;
energy = energy - 1;
render();
}
if означает «если». Выражение в круглых скобках вычисляется в логическое значение: true или false. Если оно истинно, выполняется блок в фигурных скобках. <= проверяет «меньше или равно». При нулевой энергии выполняется return; — немедленный выход из текущей функции. Поэтому строки прибавления и расхода ниже уже не исполнятся. Возврат вычисленного значения изучим отдельно; здесь значение не возвращаем.
Проверка step-01: после десяти сборов 10/0. Одиннадцатый и двенадцатый ничего не меняют. Отдых возвращает 10 энергии. Проверь также функцию напрямую в Console: energy = 0; handleGather(); не должна прибавить очко. После проверки в консоли обновляй страницу.
Как сравнивать значения и объединять условия
> и < сравнивают строго; >= и <= включают границу. === проверяет строгое равенство: 10 === 10 истинно, а 10 === '10' ложно, потому что типы различаются. Один знак = по-прежнему присваивает. Не используй его вместо сравнения в условии.
&& означает «и»: для покупки должно хватать кристаллов, а улучшение ещё не должно быть куплено. || означает «или»: действие запрещено, если партия окончена или энергии нет. ! меняет логическое значение на противоположное. Например, !upgraded истинно до покупки. Скобки помогают явно выделить выражение, которое мы отрицаем.
console.log(9 >= 10); // false
console.log(10 >= 10); // true
console.log(11 >= 10); // true
console.log(10 >= 10 && !false); // true
Добавляем покупку улучшения
В index.html внутрь блока actions, после отдыха, добавь кнопку:
<button id="upgrade-button" type="button">Улучшить за 10</button>
Рядом с поиском других кнопок в game.js найди новый элемент. Перед регистрацией событий добавь обработчик, а регистрацию размести рядом с остальными:
const upgradeButton = document.getElementById('upgrade-button');
function handleUpgrade() {
if (won || upgraded || !(score >= upgradePrice)) {
return;
}
score = score - upgradePrice;
clickPower = 2;
upgraded = true;
render();
}
upgradeButton.addEventListener('click', handleUpgrade);
Цена upgradePrice уже объявлена равной 10. Флаг upgraded до покупки равен false. Условие можно прочитать так: «выйти, если уже победили, уже купили или кристаллов недостаточно». После удачной покупки списываем ровно 10, меняем силу и ставим флаг. На следующем сборе прибавится 2. Вторая покупка ничего не делает, даже если снова накопить деньги.
Проверка step-02: при 9 кристаллах покупка не меняет ни очки, ни силу. При ровно 10 она оставляет 0 и силу 2. При 11 оставит 1. Для проверки удобнее в Console выполнить score = 9; render();, затем нажать кнопку. Перед каждым следующим случаем обновляй страницу, чтобы upgraded снова был false. В этой промежуточной версии победы ещё нет.
Добавляем завершение партии и сообщение
В handleGather расширь первый запрет и после расхода энергии добавь проверку цели. Замени функцию целиком:
function handleGather() {
if (won || energy <= 0) {
return;
}
score = score + clickPower;
energy = energy - 1;
if (score >= winningScore) {
won = true;
}
render();
}
Используем >=, чтобы не пропустить победу когда после улучшения счёт вырастет сразу с 19 до 21. Для победы нужно иметь 20 кристаллов в запасе. Потраченные на улучшение кристаллы не учитываются; победить можно и без покупки. В начало handleRest также добавь if (won) { return; }, чтобы после окончания партии отдых не менял данные. У покупки такая защита уже есть.
Теперь замени render этим вариантом:
function render() {
scoreElement.textContent = score;
energyElement.textContent = energy;
powerElement.textContent = clickPower;
if (won) {
statusElement.textContent = 'Победа! Ты собрал 20 кристаллов.';
} else if (energy === 0) {
statusElement.textContent = 'Энергия закончилась. Нажми «Отдохнуть».';
} else {
statusElement.textContent = 'Цель: 20 кристаллов. Улучшение за 10 удваивает силу.';
}
gatherButton.disabled = won || energy <= 0;
restButton.disabled = won;
upgradeButton.disabled = won || upgraded || score < upgradePrice;
}
else if проверяет следующий случай, только если предыдущий не подошёл; else — всё оставшееся. Сначала проверяем победу, затем запас энергии. Если последним ходом игрок набрал нужные очки и потратил последнюю единицу энергии, показываем поздравление с победой.
disabled — свойство кнопки. Значение true делает её недоступной для обычного нажатия. В render мы вычисляем это состояние из тех же данных, но не меняем сами очки. Проверки в обработчиках тоже оставляем: они не дадут нарушить правило, даже если вызвать функцию из консоли.
Самостоятельно: два условия для улучшения
Сделай отдельную копию final. Измени правило: покупка разрешена, только если хватает кристаллов и осталось хотя бы 1 энергии. Улучшение по-прежнему можно купить один раз и только до победы. Обнови и обработчик, и доступность кнопки. Проверь пары score/energy: 9/1, 10/0, 10/1. В первых двух покупка запрещена, в третьем разрешена.
Подсказка 1
Сначала вырази разрешённый случай: достаточно очков и энергия положительна. Потом сформулируй случаи запрета. Не списывай цену до проверки.
Подсказка 2
К существующему условию выхода можно через || добавить energy <= 0. Тот же случай добавь к upgradeButton.disabled. Эквивалентное разрешение: score >= upgradePrice && energy > 0.
Эту вариацию сохрани отдельно. В следующий урок идём с базовым final: покупка требует только 10 кристаллов, некупленного улучшения и незавершённой партии.
Что проверить в готовой версии
- От 0 до 10 очков энергия доходит до нуля и не становится отрицательной.
- Покупка при 9/10/11 имеет три ожидаемых результата; вторая покупка запрещена.
- Десять сборов, отдых и ещё десять сборов без улучшения дают победу на 20.
- Десять сборов, покупка, отдых и ещё десять сборов с силой 2 также заканчивают партию.
- После победы прямые вызовы обработчиков в Console не меняют состояние.
Готово, когда: ты можешь объяснить, почему при 9 кристаллах покупка запрещена, а при 10 — разрешена, и найти условие, которое это проверяет. Временный сброс здесь — обновление страницы; собственную кнопку полного перезапуска добавим при сборке проекта.
Разбор самостоятельного задания
Сначала попробуй решить задание сам. Затем сравни с примером ту функцию или условие, которые вызвали затруднение. Разбор самостоятельной задачи доступен во вкладке «Решение» в просмотрщике исходников.