Пишем тренажер слепой печати на чистом 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(); // игра началась         }     } } 

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

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

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


ссылка на оригинал статьи https://habr.com/ru/company/otus/blog/480118/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *