Гид по технологиям

Как создать Wordle на JavaScript — пошаговое руководство

8 min read JavaScript Обновлено 11 Apr 2026
Как создать Wordle на JavaScript
Как создать Wordle на JavaScript

Женщина у компьютера с иллюстрацией Wordle

Как работает Wordle

В Wordle зашифровано секретное слово из пяти букв. У игрока есть шесть попыток, чтобы угадать это слово, вводя разные пятибуквенные слова.

После отправки догадки игра сообщает о совпадениях через цвета:

  • жёлтый: буква есть в слове, но стоит в другой позиции;
  • зелёный: буква есть и на правильной позиции;
  • серый: буквы в слове нет.

Пояснение механики Wordle

Определения в один абзац:

  • Тайл (тайл/ячейка): отдельная клетка на доске для одной буквы.
  • Ряд: строка из 5 тайлов; всего 6 рядов.
  • Секретное слово: слово, которое нужно угадать, хранится в переменной secretWord.

Развёртывание dev-сервера

Код проекта опубликован в репозитории на GitHub и распространяется по лицензии MIT. Если вы хотите посмотреть живой demo, используйте ссылку в репозитории.

Проект использует Vite для быстрого старта. Рекомендуется иметь Yarn (обычно быстрее npm). Выполните в терминале:

yarn create vite  

Выберите фреймворк: Vanilla, вариант: JavaScript. Затем установите зависимости:

yarn  

Запустите dev-сервер:

yarn dev

Примечание: если вы предпочитаете npm, можно заменить команды на эквиваленты npm — функционально примеры остаются теми же.

Настройка игры и клавиатуры

Откройте проект в редакторе кода. Очистите main.js и убедитесь, что структура папок соответствует ожидаемой (например, index.html, main.js, style.css и т.д.).

Структура проекта в файловой системе

Замените содержимое index.html на каркас ниже (код сохранён без изменений):

  
  
  
  
    
    
    
  JS Wordle  
  
  
  
    
    
      

Wordle Clone

               Replay         Show Answer       
      Please wait. The Game is loading...
    
           
        
    
     

Для стилей возьмите файл style.css из репозитория проекта и вставьте в свой style.css.

Установите Toastify для уведомлений:

yarn add toastify -S  

В main.js импортируйте css и Toastify (код сохранён без изменений):

import "./style.css"  
import Toastify from 'toastify-js'  

Определите основные переменные для удобной работы с DOM (код сохранён без изменений):

let board = document.querySelector("#board");  
let message = document.querySelector("#message");  
let keys = "QWERTYUIOPASDFGHJKLZXCVBNM".split("");  
let restartBtn = document.querySelector("#restart-btn");  
let showBtn = document.querySelector("#show-btn");  
showBtn.setAttribute("disabled", "true");  
keys.push("Backspace");  
let keyboard = document.querySelector(".keyboard");  

Важно: HTML в проекте оставлен на английском, чтобы код совпадал с примерами. Вы можете локализовать текст кнопок и сообщений, но тогда убедитесь, что селекторы и data-атрибуты корректно соответствуют обработчикам событий.

Настройка доски игры

Так как Wordle использует 6 попыток по 5 букв, объявим boardContent — массив из шести массивов. Также объявим currentRow и currentBox для навигации по доске (код сохранён без изменений):

let boardContent = [  
    [0, 0, 0, 0, 0],  
    [0, 0, 0, 0, 0],  
    [0, 0, 0, 0, 0],  
    [0, 0, 0, 0, 0],  
    [0, 0, 0, 0, 0],  
    [0, 0, 0, 0, 0],  
];  
let currentRow = 0;  
let currentBox = 0;  
let secretWord;  

Для рендеринга доски используйте вложенные циклы, создавая по 5 span-элементов в каждом ряду (код сохранён без изменений):

for (let i = 0; i <= 5; i++) {  
    let row = document.createElement('div')  
    for (let y = 0; y <= 4; y++) {  
        let box = document.createElement('span');  
        row.appendChild(box);  
        row.className = `row-${i + 1}`  
    }  
    board.appendChild(row);  
}

Совет UX: добавьте aria-атрибуты и tabindex для тайлов, если планируете поддерживать клавиатурную навигацию и вспомогательные технологии.

Добавление клавиатуры и обработка ввода

Клавиатура создаётся простым перебором keys: для каждой записи создаём кнопку, присваиваем ей класс key и data-key, навешиваем клик, который вызывает insertKey. (код сохранён без изменений):

keys.forEach(entry => {  
    let key = document.createElement("button");  
    if (entry === "*") {  
        key.innerText = "Backspace";  
    } else {  
        key.innerText = entry;  
    }  
    key.className = "key";  
    key.setAttribute("data-key", entry.toUpperCase());  
    key.addEventListener("click", () => {  
        insertKey(entry.toUpperCase())  
        setTimeout(() => {  
            document.querySelector(`button[data-key=${entry.toUpperCase()}]`).blur();  
        }, 250)  
    })  
    keyboard.append(key);  
})  

Обратите внимание: в различных раскладках клавиатур символы и регистр могут отличаться. Функция isValidCharacter (ниже) решает, какие символы считаются допустимыми.

Получение слова из API

При загрузке игра получает случайное пятибуквенное слово из Random Word API и сохраняет его в secretWord (код сохранён без изменений):

function getNewWord() {  
    async function fetchWord() {  
        try {  
            const response = await fetch("https://random-word-api.herokuapp.com/word?length=5");  
            if (response.ok) {  
                const data = await response.json();  
                return data;  
            } else {  
                throw new Error("Something went wrong!")  
            }  
        } catch (error) {  
            message.innerText = `Something went wrong. \n${error}\nCheck your internet connection.`;  
        }  
    }  
    fetchWord().then(data => {  
        secretWord = data[0].toUpperCase();  
        main();  
    })  
  
}

Важно: публичные API могут возвращать неподходящие слова (редкие или устаревшие). Для продакшена рассмотрите собственный словарь с контролем допустимых слов.

Основная функция и рендеринг

Функция main запускается после успешного получения слова. Её задача — подготовить список всех тайлов, скрыть сообщение загрузки и навесить глобальный обработчик клавиатуры (фрагменты кода сохранены без изменений):

function main(){  
  
}  

Внутри main соберите все row-элементы в один массив boxes, добавьте класс empty для непустых тайлов и скройте сообщение загрузки (код сохранён без изменений):

    rows.forEach(row => [...row.children].forEach(child => boxes.push(child)))  
    boxes.forEach((box) => {  
        box.classList.add("empty");  
    })  
    message.style.display = "none";  

Добавьте обработчик keyup на window: если пользователь отпустил допустимую клавишу, найдите соответствующую кнопку, сфокусируйте её, сымитируйте клик и снимите фокус через 250 мс (код сохранён без изменений):

    window.addEventListener('keyup', (e) => {  
        if (isValidCharacter(e.key)) {  
            document.querySelector(`button[data-key=${e.key.toUpperCase()}]`).focus();  
            document.querySelector(`button[data-key=${e.key.toUpperCase()}]`).click();  
            setTimeout(() => {  
                document.querySelector(`button[data-key=${e.key.toUpperCase()}]`).blur();  
            }, 250)  
        }  
    })  

После этого добавьте обработчики на кнопки showBtn и restartBtn, а также функцию isValidCharacter (код сохранён без изменений):

    showBtn.addEventListener('click', () => {  
        Toastify({  
            text: `Alright fine! the answer is ${secretWord}`,  
            duration: 2500,  
            className: "alert",  
        }).showToast();  
    })  
  
    restartBtn.addEventListener('click', () => {  
        location.reload();  
    })  
    function isValidCharacter(val) {  
        return (val.match(/^[a-zA-Z]+$/) && (val.length === 1 || val === "Backspace"))  
    }  

Совет: для поддержки локализации можно хранить ключевые тексты (например, сообщения и надписи кнопок) в отдельном объекте переводов.

Рендеринг отдельной ячейки

Функция renderBox обновляет текст в конкретной ячейке (код сохранён без изменений):

function renderBox(row, box, data) {  
    [...document.querySelector(`.row-${row}`).children][box].innerText = data;  
}  

Обработка нажатий клавиш и вставка символов

Функция insertKey обновляет boardContent, рендерит буквы в текущую ячейку и переводит ход на следующий ряд, если ряд заполнен (код сохранён без изменений):

function insertKey(key) {  
    if (key === "Backspace".toUpperCase() && currentRow < boardContent.length) {  
        boardContent[currentRow][currentBox] = 0;  
        if (currentBox !== 0) {  
            currentBox--;  
            renderBox(currentRow + 1, currentBox, "");  
        }  
    } else {  
        if (currentRow < boardContent.length) {  
            boardContent[currentRow][currentBox] = key;  
            renderBox(currentRow + 1, currentBox, key);  
            currentBox++;  
        }  
        if (currentRow < boardContent.length && boardContent[currentRow][currentBox] !== 0) {  
            evaluate(currentRow, key);  
            currentBox = 0;  
            currentRow++;  
        }  
    }  
}

Замечание: логика переключения currentBox/currentRow предполагает, что проверка заполнения ряда происходит после записи последней буквы. При редактировании алгоритма будьте осторожны с индексами, чтобы не выходить за границы массива.

Оценка догадки игрока

Функция evaluate принимает номер ряда и вычисляет цвета для каждой буквы: зелёный — правильная буква на месте, жёлтый — буква есть в слове, но не на месте, серый — буквы нет. Также начиная с четвёртой попытки показывается кнопка “Show Answer” (код сохранён без изменений):

function evaluate(row){  
  
}

Внутри найдём догадку и массив для сравнения (код сохранён без изменений):

if (currentRow === 4) {  
    showBtn.removeAttribute('disabled')  
}  

let guess = boardContent[row].join('').toUpperCase();  
let answer = secretWord.split("");  

Алгоритм подсветки реализован через два прохода: сначала помечаем точные совпадения, затем ищем оставшиеся буквы для жёлтого/серого статуса (код сохранён без изменений):

let colors = guess  
    .split("")  
    .map((letter, idx) => letter == answer[idx] ? (answer[idx] = false) : letter)  
    .map((letter, idx) =>  
        letter  
            ? (idx = answer.indexOf(letter)) < 0  
                ? "grey"  
                : (answer[idx] = "yellow")  
            : "green"  
);  

Затем применяем цвета к тайлам и кнопкам клавиатуры с помощью setColor (код сохранён без изменений):

function setColor(colors) {  
        colors.forEach((color, index) => {  
            document.querySelector(`button[data-key=${guess[index].toUpperCase()}]`).style.backgroundColor = color;  
            document.querySelector(`button[data-key=${guess[index].toUpperCase()}]`).style.color= "black";  
            [...document.querySelector(`.row-${row + 1}`).children][index].style.backgroundColor = color;  
        })  
}  

Замечание по алгоритму: метод, использованный здесь, мутирует массив answer, чтобы учесть повторяющиеся буквы корректно. Это типичный подход для Wordle-подобных игр.

Завершение и запуск

Чтобы начать игру, вызовите getNewWord(); (код сохранён без изменений):

getNewWord();  

Поздравляем — вы воссоздали базовую версию Wordle на JavaScript!

Готовая игра Wordle в браузере

Советы по улучшению и альтернативные подходы

Ниже — практические рекомендации, расширения и чеклисты, которые помогут сделать проект надёжнее, удобнее и более зрелым.

Альтернативные подходы к получению слов

Когда не годится случайное API: в офлайн-приложениях, при строгой цензуре слов или когда нужен контроль частоты появления слов.

Модели мышления и эвристики при разработке

Мини-методология разработки (быстрый план)

  1. Подготовка: scaffold Vite + пустые файлы.
  2. Разметка: index.html — доска, клавиатура, контролы.
  3. Рендеринг: динамически создаём DOM-тайлы и клавиши.
  4. Логика: boardContent, insertKey, renderBox.
  5. Оценка: evaluate + setColor.
  6. Тесты: ручные и автоматизированные (unit-тесты для evaluate).
  7. Улучшения: локализация, словарь, статистика, анимации.

Роль‑ориентированные чеклисты

Тестовые случаи и критерии приёмки

Отладка и отлов ошибок

Производительность и безопасность

Локализация и адаптация для России

Примеры улучшений UX

Decision tree: игровой цикл (Mermaid)

flowchart TD
  Start'Запуск' --> Fetch{Получено слово?}
  Fetch -- Да --> RenderBoard'Рендер доски'
  Fetch -- Нет --> Error[Показать ошибку и fallback]
  RenderBoard --> Input[Ожидание ввода]
  Input --> Update[insertKey обновляет доску]
  Update --> FullRow{Ряд заполнен?}
  FullRow -- Да --> Eval[evaluate + setColor]
  FullRow -- Нет --> Input
  Eval --> Win{Слово угадано?}
  Win -- Да --> End[Победа — показать диалог]
  Win -- Нет --> Attempts{Попытки закончились?}
  Attempts -- Нет --> Input
  Attempts -- Да --> Reveal[Показать ответ]

Короткое объявление для соцсетей (100–200 слов)

Создал простой клон Wordle на чистом JavaScript с Vite и Toastify. В репозитории есть весь код: рендеринг доски, виртуальная клавиатура, получение случайного слова через API и алгоритм подсветки букв. Подойдёт как учебный проект для начинающих: учит DOM‑манипуляциям, обработке событий и работе с fetch. В статье — чеклисты для тестировщиков, советы по локализации и идеи для улучшений (локальный словарь, локализация для кириллицы, хранение прогресса в localStorage). Ссылка на демо и инструкции по быстрому запуску — в репозитории.

Итоги

Важно: сохраняйте логику оценки игровых правил отдельно от DOM‑кода — это облегчает тестирование и переносимость на другие платформы (React, Svelte, сервер). Для продакшена подумайте о локальном словаре, тестах на повторяющиеся буквы и поддержке нескольких раскладок клавиатуры.

Ключевые шаги для старта: scaffold Vite → подключить Toastify → сгенерировать DOM для доски и клавиатуры → реализовать insertKey → реализовать evaluate → получить слово из API или локального словаря → запустить getNewWord().

Важно: если вы собираетесь локализовать игру на русский язык, замените проверки символов и словарь на набор слов на кириллице и протестируйте обработку ё/е.

Счастливого кодинга — и удачи в угадывании секретного слова!

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Gmail и настольные клиенты: выбор и настройка
Почта

Gmail и настольные клиенты: выбор и настройка

SketchUp бесплатно: как начать 3D‑моделирование
3D моделирование

SketchUp бесплатно: как начать 3D‑моделирование

Как создать аккаунт PlayStation Network (PSN)
Руководство

Как создать аккаунт PlayStation Network (PSN)

Почему iPhone и iPad нагреваются и как это исправить
Мобильные устройства

Почему iPhone и iPad нагреваются и как это исправить

Как искать жильё на Airbnb для отпуска
Путешествия

Как искать жильё на Airbnb для отпуска

Arduino Pong: ретро-игра на TV
Arduino

Arduino Pong: ретро-игра на TV