← Назад к курсу

⚡ Урок 3: JavaScript логика

Программируем логику игры "Угадай число"

🎯 Цель урока

В этом уроке мы создадим полную логику игры "Угадай число" на JavaScript. Изучим генерацию случайных чисел, валидацию пользовательского ввода и создание интерактивного геймплея.

Ты узнаешь, как обрабатывать события, управлять состоянием игры и создавать отзывчивый пользовательский интерфейс с помощью JavaScript.

🎮 Интерактивная демонстрация

Попробуй угадать число от 1 до 20:

Загаданное число: ?
Введи число от 1 до 20 и нажми "Проверить"
Попыток: 0 / 7

🎲 Генерация случайного числа

Основа любой игры "Угадай число" - генерация случайного числа. 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 в зависимости от состояния игры:

1
Найти элементы DOM
Получаем ссылки на HTML элементы через селекторы
2
Обработать событие
Реагируем на клики кнопок или нажатие Enter
3
Обновить интерфейс
Меняем текст, цвета, добавляем CSS классы
4
Сохранить состояние
Обновляем переменные игры для следующего хода
🔄 DOM манипуляции
// Обновляем интерфейс игры
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 логику для игры "Угадай число":

  1. Создай класс NumberGuessingGame с конструктором
  2. Реализуй генерацию случайного числа
  3. Добавь метод валидации пользовательского ввода
  4. Создай логику проверки попытки
  5. Реализуй обновление DOM элементов
  6. Добавь обработчики событий для кнопок
  7. Реализуй обработку клавиши Enter
  8. Добавь функцию новой игры
  9. Протестируй все сценарии игры

💡 Помни: хорошая логика - это правильная обработка всех возможных случаев!

Следующий урок: Умные алгоритмы →