Пишем тренажер слепой печати на чистом JavaScript. Часть 1

    Здравствуйте! В преддверии старта курса «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(); // игра началась
            }
        }
    }
    

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

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

    Вот такой получился материал. Напоминаем о том, что данный материал написан внештатным автором и не имеет отношения к образовательному процессу. Если вы заинтересованы в образовании и хотите узнать о курсе подробнее, приглашаем на день открытых дверей, который пройдет уже в понедельник.
    OTUS. Онлайн-образование
    389,73
    Цифровые навыки от ведущих экспертов
    Поделиться публикацией

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

    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

    Самое читаемое