
Всем привет! Сегодня я решил показать, как написать свой тренажер слепой печати на 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/
Добавить комментарий