🎯 Цель урока
В этом уроке мы создадим полную логику игры "Угадай число" на JavaScript. Изучим генерацию случайных чисел, валидацию пользовательского ввода и создание интерактивного геймплея.
Ты узнаешь, как обрабатывать события, управлять состоянием игры и создавать отзывчивый пользовательский интерфейс с помощью JavaScript.
🎮 Интерактивная демонстрация
Попробуй угадать число от 1 до 20:
🎲 Генерация случайного числа
Основа любой игры "Угадай число" - генерация случайного числа. JavaScript предоставляет функцию Math.random() для этой цели.
// Класс для управления игрой class NumberGuessingGame { constructor(minRange = 1, maxRange = 50) { this.minRange = minRange; this.maxRange = maxRange; this.maxAttempts = 7; this.attempts = 0; this.gameActive = false; this.secretNumber = null; // Инициализируем игру this.initializeGame(); } // Генерируем случайное число в диапазоне generateRandomNumber(min, max) { // Math.random() возвращает число от 0 до 1 // Умножаем на диапазон и добавляем минимум return Math.floor(Math.random() * (max - min + 1)) + min; } // Начинаем новую игру initializeGame() { this.secretNumber = this.generateRandomNumber(this.minRange, this.maxRange); this.attempts = 0; this.gameActive = true; console.log(`Загадано число: ${this.secretNumber}`); this.updateGameDisplay(); } }
Math.floor() округляет вниз до целого числа. Формула (max - min + 1) гарантирует включение обеих границ диапазона.
🧠 Логика проверки попытки
Пошаговый алгоритм обработки пользовательского ввода:
// Проверяем попытку игрока checkGuess(userGuess) { // Проверяем, активна ли игра if (!this.gameActive) { return { success: false, message: "Игра завершена! Начни новую игру.", type: "info" }; } // Валидируем ввод const validation = this.validateInput(userGuess); if (!validation.valid) { return { success: false, message: validation.message, type: "error" }; } // Увеличиваем счётчик попыток this.attempts++; // Сравниваем с загаданным числом if (userGuess === this.secretNumber) { this.gameActive = false; return { success: true, message: `🎉 Поздравляю! Ты угадал число ${this.secretNumber} за ${this.attempts} попыток!`, type: "success", attempts: this.attempts }; } // Проверяем, остались ли попытки if (this.attempts >= this.maxAttempts) { this.gameActive = false; return { success: false, message: `😔 Попытки закончились! Загаданное число было ${this.secretNumber}.`, type: "defeat" }; } // Даём подсказку const hint = userGuess > this.secretNumber ? "📉 Моё число меньше" : "📈 Моё число больше"; const remainingAttempts = this.maxAttempts - this.attempts; return { success: false, message: `${hint}. Осталось попыток: ${remainingAttempts}`, type: userGuess > this.secretNumber ? "high" : "low", attempts: this.attempts }; }
✅ Валидация пользовательского ввода
Важно проверять все данные, которые вводит пользователь:
Проверка типа
Убеждаемся, что введено именно число, а не текст
Диапазон значений
Число должно быть в пределах игрового диапазона
Целое число
Не допускаем дробные числа в игре с целыми числами
Пустой ввод
Обрабатываем случай, когда ничего не введено
// Валидируем пользовательский ввод validateInput(input) { // Проверяем, что ввод не пустой if (input === null || input === undefined || input === "") { return { valid: false, message: "❌ Пожалуйста, введи число!" }; } // Преобразуем в число const number = Number(input); // Проверяем, что это корректное число if (isNaN(number)) { return { valid: false, message: "❌ Это не число! Введи цифры." }; } // Проверяем, что число целое if (!Number.isInteger(number)) { return { valid: false, message: "❌ Введи целое число, без дробей!" }; } // Проверяем диапазон if (number < this.minRange || number > this.maxRange) { return { valid: false, message: `❌ Число должно быть от ${this.minRange} до ${this.maxRange}!` }; } // Всё в порядке! return { valid: true, message: "✅ Число корректно" }; }
🔄 Управление состоянием игры
JavaScript позволяет динамически обновлять HTML в зависимости от состояния игры:
Получаем ссылки на HTML элементы через селекторы
Реагируем на клики кнопок или нажатие Enter
Меняем текст, цвета, добавляем CSS классы
Обновляем переменные игры для следующего хода
// Обновляем интерфейс игры updateGameDisplay(result = null) { // Получаем ссылки на элементы const resultElement = document.getElementById('gameResult'); const attemptsElement = document.getElementById('attemptsCount'); const inputElement = document.getElementById('guessInput'); const buttonElement = document.getElementById('guessButton'); // Обновляем счётчик попыток if (attemptsElement) { attemptsElement.textContent = this.attempts; } // Если есть результат проверки if (result && resultElement) { // Обновляем текст сообщения resultElement.textContent = result.message; // Убираем старые CSS классы resultElement.className = 'result-message'; // Добавляем новый класс в зависимости от типа switch (result.type) { case 'success': resultElement.classList.add('result-success'); this.disableInput(); break; case 'defeat': resultElement.classList.add('result-defeat'); this.disableInput(); break; case 'high': resultElement.classList.add('result-high'); break; case 'low': resultElement.classList.add('result-low'); break; default: resultElement.classList.add('result-info'); } } // Очищаем поле ввода if (inputElement) { inputElement.value = ''; inputElement.focus(); } }
⌨️ Обработка событий
Для создания интерактивного интерфейса нужно обрабатывать события - клики мыши, нажатия клавиш, изменения в полях ввода.
// Инициализация обработчиков событий initializeEventListeners() { const guessButton = document.getElementById('guessButton'); const guessInput = document.getElementById('guessInput'); const newGameButton = document.getElementById('newGameButton'); // Обработка клика по кнопке "Проверить" if (guessButton) { guessButton.addEventListener('click', () => { const userGuess = parseInt(guessInput.value); const result = this.checkGuess(userGuess); this.updateGameDisplay(result); }); } // Обработка Enter в поле ввода if (guessInput) { guessInput.addEventListener('keypress', (event) => { if (event.key === 'Enter') { // Симулируем клик по кнопке guessButton.click(); } }); // Валидация при вводе guessInput.addEventListener('input', (event) => { const value = event.target.value; // Удаляем некорректные символы if (value && isNaN(value)) { event.target.value = value.replace(/[^0-9]/g, ''); } // Проверяем диапазон const number = parseInt(event.target.value); if (number > this.maxRange) { event.target.value = this.maxRange; } }); } // Кнопка новой игры if (newGameButton) { newGameButton.addEventListener('click', () => { this.initializeGame(); }); } }
addEventListener() позволяет
привязать функцию к событию.
arrow функции сохраняют контекст
this.
⚡ Твоё задание
Создай полную JavaScript логику для игры "Угадай число":
- Создай класс NumberGuessingGame с конструктором
- Реализуй генерацию случайного числа
- Добавь метод валидации пользовательского ввода
- Создай логику проверки попытки
- Реализуй обновление DOM элементов
- Добавь обработчики событий для кнопок
- Реализуй обработку клавиши Enter
- Добавь функцию новой игры
- Протестируй все сценарии игры
💡 Помни: хорошая логика - это правильная обработка всех возможных случаев!