Здравствуйте! В преддверии старта курса «Fullstack разработчик JavaScript» один из наших авторов решил поделиться своим опытом создания тренажера для слепой печати. А мы же, в свою очередь, хотим показать вам данный материал.




Всем привет! Сегодня я решил показать, как написать свой тренажер слепой печати на JavaScript. Я думаю, каждый из нас в начале пути тренировал свою печать — ведь это один из важнейших навыков разработчика
.

В интернете существует множество сайтов и программ, с помощью которых можно и отточить свои навыки печати, и немного развлечься. Есть игры для детей, есть игры, в которых вы можете соревноваться с другим человеком, кто печатает быстрее! Но положим, мы хотим создать тренажер печати с таким оформлением и скоростью, как мы сами захотим. И сегодня мы попробуем написать первую часть нашего приложения, но в которую можно будет поиграть уже сейчас.



Итак, в качестве фреймворка для верстки я выбрал Bulma.css. Bulma достаточно разнообразна, и с ее помощью можно обойтись без написания своего css как минимум на первом этапе.

Итак, начнем с создания основной страницы. Что бы не тратить место на одинаковый у всех код, скажу, что в тэге head я подключил файл javascript, bulma, и favicon.

<body>
    <section class="hero is-primary is-large">
        <!-- воспользуемся готовым элементом hero из bulma -->
        <div class="hero-head container"> 
            <h1 class="label is-size-3 has-text-white promo"> Наш простой тренажер</h1>
            <h3 class="label is-size-4 has-text-link has-text-centered">Ошибки</h3>
            <progress  id="prog" class="progress is-danger" value="0" max="20"></progress>
            <h3 class="label is-size-5 has-text-white has-text-centered begin">Press Enter to Start</h3>
        </div>
        <div class="hero-body has-background-grey-dark ">
            <div id="columns">
                <div class="buttons columns is-half is-centered ">
                    <!-- и здесь у нас будет происходить отрисовка  -->
                </div>
            </div>
        </div>
    </section>
</body>

Мы делаем небольшую панель, в которой есть приглашение для нашего пользователя поиграть, нажав клавишу Enter. В элемент buttons у нас будут рисоваться наши кнопки, которые будут рандомно сгенерированы нашим JS. В идеале прогресс с ошибками должен быть скрыт до начала игры, возможно, мы исправим это в следующей части.

Окей, index.html готов, а всю заботу за красоту и верстку на себя взяла bulma. Теперь мы можем погрузиться в наш js.

Какие клавиши на клавиатуре тренируют в первую очередь? Думаю, все в курсе, что ваши указательные пальцы должны лежать на клавишах j и f (наше приложение будет разбирать английскую раскладку, как самую полезную (программисты 1С, простите меня, если сможете)). Средние пальцы должны находиться на k и d соответственно, и кроме того важно, чтобы во время тренировки мы нажимали еще и на пробел. Итого, в нашем первоначальном варианте нам нужно будет 5 символов.

Сказано — сделано. Создаем массив, в котором находятся все наши клавиши. Кроме того, мы создадим массив цветов, потому что тренажер, в котором все буквы одноцветные, очень скучный и неудобный:

let colors = ['is-info', 'is-success', 'is-warning', 'is-danger', 'is-link'];
//классы фреймворка bulma, в которые мы будем красить наши кнопки
//при каждой генерации мы будем назначать каждому символу свой цвет, чтобы пользователь при печати не путался
let str_arr = ['j', 'f', 'k', 'd', ' '];

Отлично, с набором цветов и символами мы определились. Дальше получим все необходимые для дальнейшей работы элементы DOM:

let begin = document.querySelector(".begin"); // здесь у нас надпись, которая приглашает пользователя нажать Enter для начала игры.
let progress = document.getElementById("prog"); // здесь отображается прогресс ошибок пользователя
let buttons = document.querySelector('.buttons'); // элемент в который мы будем писать наши буковки

Здорово, основные элементы получены. Теперь можно приступать к созданию логики нашего приложения. Создаем функцию, которая с помощью рандомного генератора будет генерировать нам наши символы. Сначала приведем код функции, которая возвращает нам рандомные числа от 0 до заданного максимального числа. Это классическая функция генерации рандомного числа из документации MDN:

function getRandomInt(max) {
    return Math.floor(Math.random() * Math.floor(max));
}

Окей, теперь все готово, пора приступать к генерации DOM — элементов:

function drawBoard() {
    for (let index = 0; index < 20; index++) { // в идеале показатель количества символов пользователь должен иметь возможность изменить
    let rand = getRandomInt(colors.length); // здесь у нас массив символов и цветов одинаковый по длине, поэтому неважно, откуда брать длину
        buttons.insertAdjacentHTML("afterbegin",
        `<button class='game-buttons button is-large 
        ${colors[rand]}' id='${str_arr[rand]}'>${str_arr[rand]}			
        </button>`);
    }
}

Функция готова, теперь её нужно вызвать. Напоминаю, что старт игры у нас происходит по нажатию на клавишу Enter, и мы еще хотим скрыть приглашающую надпись. Однако игра и рисовка должна вызываться у нас только один раз, поэтому мы используем для addEventListener аргумент once:

document.addEventListener('keydown', StartGame, {
    once: true
    //благодаря once у нас отрисовка вызывается только один раз
});

И вот сама функция StartGame:

function StartGame(e) {
    if (e.key == "Enter") {
        drawBoard();
        begin.style.display = "none"; // скрываем приглашающую кнопку
        mainGame(); // игра началась
    }
}

В mainGame у нас происходит прослушивание всех нажатых кнопок, чтобы можно было понимать, правильно ли пользователь нажимает кнопки на клавиатуре, или нет:

function mainGame() {
    document.addEventListener('keyup', press); //  я создал отдельную функцию, что бы была возможность ее удалять из прослушивателя
}

Итак, такими переподключениями функций мы добрались до основной игры. Давайте подумаем, какие переменные нам необходимы? Нужна переменная, которая будет считать наши ошибки и переменная, к которой мы будем добавлять значения при успешном нажатии:

var count_right = 0;

var errors_count = 0;

Окей, самое основное и вкусное впереди. Для универсальности, чтобы наше приложение не было так зависимо от русской и английской раскладки, мы могли воспользоваться keyCode, но это усложнит код. Нам нужно получить все нагенерированные символы и, если клавиша на клавиатуре совпадает с id нашего элемента (обратите внимание, я ещё в drawBoard() задал каждому элементу id, которое равно текстовому содержимому элемента. Вне сомнения, можно было просто прочесть содержание через textContent, и в будущем, возможно, мы так и сделаем), тогда элемент удаляется. В другом случае, добавим значение в переменную, которая считает ошибки пользователя и пишет их внутрь progress:

function press(e) {
    let elements_arr = document.querySelectorAll(".game-buttons");  // выбираем все созданные кнопки

    if (e.key == elements_arr[0].id) { // здесь можно выбирать и по querySelector, но тогда код будет длиннее
        elements_arr[0].remove();
        count_right++; //  считаем правильные ответы
    } else {
        errors_count++; // считаем ошибки
        progress.value = errors_count;
        if (errors_count > 20) { // если пользователь допустит ошибок больше чем у нас букв, игра закончится
            let fail = confirm("Game over! Хотите еще раз поиграть?"); 
            if (fail) {
                document.location.reload(); // перезагрузка страницы если пользователь согласился еще раз играть
            } else {
                // здесь могла быть ваша реклама
                document.addEventListener('keyup', press);
            }
        }
    }
    if (count_right == 20) {
        alert("Вы выйграли!");
        let win = confirm("Хотите поиграть еще?");
        if(win){
            drawBoard();
            begin.style.display = "none"; // скрываем приглашающую кнопку
            mainGame(); // игра началась
        }
    }
}

Здорово! Теперь наше приложение должно быть готово и его можно потестировать.

Во второй части статьи мы доработаем приложение, добавив локальное сохранение результатов, заводную музыку, звуки нажатий, анимации, таблицу лидеров, и версию приложения, заточенного только для программистов, а так же поправим незначительные баги. Если есть еще идеи и замечания — жду вас в комментариях.

Вот такой получился материал. Напоминаем о том, что данный материал написан внештатным автором и не имеет отношения к образовательному процессу. Если вы заинтересованы в образовании и хотите узнать о курсе подробнее, приглашаем на день открытых дверей, который пройдет уже в понедельник.

Комментарии (0)