Процесс создания игры «Угадай»

Добрый вечер, уважаемый читатель!

Сегодня я хотел бы рассказать, как создавал очередную небольшую игру, которую назвал «Угадай».

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

 

Как это выглядит:

 

Начнем подробный разбор, как такое сделать.

 

Верстка:

<!-- кнопка запуска игры -->
<div class="buttonStart button">
    <a href="#">Начать игру!</a>
</div>
<div class="clear_both"></div>

<!-- Статистика игры. Изначально скрыта -->
<div class="block_guess_words hide">
    Угадано <span class="guess">0</span> слов(а)<br>
    Выберите правильный перевод для слова
</div>

<!-- блоки подсказок. Изначально скрыты -->
<div class="block_answer_right hide">
    Правильно
</div>
<div class="block_answer_wrong hide">
    Неправильно
</div>

<!-- блок игры. Изначально скрыт -->
<div class="block_game hide">

    <div class="block_eng_words block">
        <div class="block_eng_word">
            Hello
        </div>
    </div>

    <div class="block_rus_words block">
        <div class="block_rus_word">
            Пока
        </div>
        <div class="block_rus_word">
            Привет
        </div>
        <div class="block_rus_word">
            Как дела?
        </div>
    </div>

    <div class="clear_both"></div>

</div>

Много букв? Разберем подробней.

Что у нас есть изначально? Есть кнопка buttonStart, при щелчке на которую будет начинаться наша игра (обработчик будет на JQuery). Изначально видна только эта кнопка. Все остальное скрыто.

Далее есть блок со статистикой block_guess_word. Он будет отображать лишь маленькую подсказку и количество отгаданных слов. Изначально скрыт. Открывается уже после запуска игры.

Далее простые блоки с подсказками block_answer_right и block_answer_wrong, правильно ли мы ответили. Каждому из блоков я дал свой класс, который будет раскрашивать блок в зеленый и красный цвет соответственно.

И напоследок основной блок игры block_game. Содержит две колонки. Левая (block_eng_words) с английским словом и правая колонка (block_rus_words) с вариантами перевода.

С верстой разобрались. Теперь стилизуем наши блоки, придадим им классный вид!

 

CSS

Начнем с наших блоков со словами:

/* разметка блоков со словами и переводами */
.block_eng_words, .block_rus_words {
    width: 200px;
    text-align: center;
}
.block_eng_words { /* левая колонка */
    float: left;
    margin-top: 105px; /* отступ сверху */
}
.block_rus_words { /* правая колонка */
    float: right; 
}
.block_rus_word {
    width: 160px;
}

 

Теперь придадим блокам вид, который должен быть у блоков 🙂

/* стили для блоков со словами */
.block div {
    background: none;
    border: 1px solid #acd373; /* обводка */

    /* закругленные уголки */
    -webkit-border-radius: 5px;
    -moz-border-radius: 5px;
    border-radius: 5px;

    /* зеленая тень вокруг блока */
    -moz-box-shadow: 0 0 5px 1px #acd373;
    -webkit-box-shadow: 0 0 5px 1px #acd373;
    box-shadow: 0 0 5px 1px #acd373;

    float: left;
    font-size: 20px;
    height: 23px;

    /* отступ блоков друг от друга */
    margin: 20px 0px;

    /* внутренние отступы текста от границ */
    padding: 20px 30px; 

    cursor: pointer;
}

Теперь наши блоки выглядят вот так:

 

Добавим немного динамики. Сделаем выделение блока при наведении мыши. Придадим зеленый задний фон и поменяем цвет текста на белый.

/* стили для наведения на блок со словом */
.block div:hover {
    background: #acd373;
    color: white;
}

Сравним то, что получилось:

По-моему, неплохо, согласны? 🙂

Сейчас приступим к самому интересному — написанию функционала для управления игрой.

 

JavaScript

Как всегда, сначала создадим JQuery обертку, без нее никуда:

var $j = jQuery.noConflict();

$j(function(){

});

 

Создадим обработчик, который повесим на кнопку начала игры:

//щелчек на кнопке играть
$j('.buttonStart a').click(function (event) {
    event.preventDefault();
    $j('.buttonStart').fadeOut(500, function () {
        $j('.block_game').fadeIn(500);
        $j('.block_guess_words').fadeIn(500);
        startGame(); // генерация уровня
    });
});

Мы написали, что по щелчку должна плавно исчезнуть кнопка и появится блок с игрой и статистикой, а далее пойдет генерация уровня. Пока что метода startGame() у нас нет, так что пока код работать не будет. Займемся же написанием метода startGame() и определим структуру документа.

function startGame() {
    getNewGameRound();
}

function getNewGameRound() {
}

/**
 * алгоритм выбора слов для нового раунда игры
 */
function renderGameRound() {
}

/**
 * генерация html кода нового уровня
 */
function printNewGameRound() {
}

/**
 * скрываем уровень для генерации нового
 */
function closeRound() {
}

Названия методов говорят сами за себя.

 

Мы описали структуру. Теперь наполним ее содержимым.

function getNewGameRound() {
    renderGameRound(); /* генерируем новый раунд игры */
    printNewGameRound(); /* печатаем игру */
}

 

Для генерации раунда необходимы данными со словами. Введем их.

var number_block = 3; // кол-во вариантов ответа перевода

var word = []; // массив слов на английском
var value = []; // массив значений слов
var index = []; // массив с итоговыми индексы слов в раунде

var selected; // выбранное слово для перевода

 

Заполнять массивы со словами нужно данными из базы данных или откуда-нибудь еще, но мы для простоты заполним массив руками:

word[0] = 'Hello';
value[0] = 'Привет';
word[1] = 'Goodbye';
value[1] = 'Досвидания';
word[2] = 'Cat';
value[2] = 'Кот';
word[3] = 'Dog';
value[3] = 'Собака';
...

 

Все данные у нас теперь есть. Займемся выбором слов для нового раунда игры.

/**
 * алгоритм выбора слов для нового раунда игры
 */
function renderGameRound() {
    var length = word.length - 1; // длина массива со словами
    var i, j;
    var bad;
    for (i = 0; i < number_block; i++) {
        // индекс слова по номеру элемента в массиве
        index[i] = getRandomInt(0, length);

        bad = false;
        // проверяем, не выбирали мы это слово до этого
        for (j = 0; j < index.length - 1; j++) {
            if (index[i] == index[j]) {
                bad = true;
                break;
            }
        }
        // повторно ищем слово, если слово повторилось
        if (bad) {
            i--;
            continue;
        }
    }

    // выбираем случайное слово, из выбранных,
    // которое надо будет переводить
    selected = getRandomInt(0, index.length - 1);
}

// Случайное целое между min и max
function getRandomInt(min, max)
{
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

 

Хорошо, слова мы выбрали. Занесли их индексы в новый массив и теперь готовы распечатать наши труды.

/**
 * генерация html кода нового уровня
 */
function printNewGameRound() {
    /* печатаем слово для перевода и даем ему специальный айдишник
    Он потребуется, чтобы проверить правильность выбора перевода */
    $j('.block_eng_word').text(word[index[selected]]);
    $j('.block_eng_word').attr('id', 'word-' + selected);

    $j('.block_rus_words').html(''); /* удалим старые слова */
    var i;
    for (i = 0; i < number_block; i++) {
        $j('.block_rus_words').html( /* разметка */

            $j('.block_rus_words').html() +
            '<div class="block_rus_word" id="translate-' + i + '">' +
                value[index[i]] +
            '</div>'

        );
    }
}

Отлично! Почти все готово! У нас теперь генерируется раунд. Мы можем пощелкать на кнопку. Попробовать выбрать перевод, но ничего не произойдет!

Давайте решим эту проблему:

// при нажатии на вариант перевода - смотрим, верно ли?
$j('body').on('click', '.block_rus_word', function () {
    var result = checkTranslate($j(this)); /* проверка перевода */

    // если угадали - то скрываем уровень и генеририуем новый
    if (result) {
        closeRound();
    }
    else {
        // показываем ошибку
        $j('.block_answer_right').fadeOut(100);
        $j('.block_answer_wrong').fadeIn(100);
    }
});

/**
 * проверяем, верно ли мы выбрали перевод слова?
 * если верно, то возвращаем true
 * иначе false
 * @param block - кнопочка с переводом, по которой мы щелкнули
 * @return true/false
 */
function checkTranslate(block) {
    var id;
    var idOrigin;

    id = block.attr("id");
    id = id.substr(id.lastIndexOf('-') + 1);//выделяем индекс (цифра)

    idOrigin = $j('.block_eng_word').attr("id");
    idOrigin = idOrigin.substr(idOrigin.lastIndexOf('-') + 1);  //выделяем индекс (цифра)

    if (id == idOrigin) { /* сравниваем айди перевода и слова */
        return true; /* отгадали слово */
    }
    return false;
}

Перевод проверили. Если игрок ошибся, то ему просто высветится подсказка. А если игрок угадал, то делаем следующее:

/**
 * скрываем уровень для генерации нового
 */
function closeRound() {
    /* увеличиваем счетчик статистики */
    $j('.guess').text(parseInt($j('.guess').text()) + 1);

    // показываем, что угадали верно
    $j('.block_answer_right').fadeIn(100);
    $j('.block_answer_wrong').fadeOut(100);

    $j('.block_game').fadeOut(500, function () {
        index = []; // удалим массив с выбранными ранее айди слов
        getNewGameRound(); /* новая генерация */
        $j('.block_game').fadeIn(500, function () {
            $j('.block_answer_right').fadeOut(100);
            $j('.block_answer_wrong').fadeOut(100);
        });
    })
}

Функция выводит подсказку, что перевод верный. Потом плавно скрывает block_game и генерирует новый уровень. После генерации block_game плавно появляется.

 

Вот и все! Ничего сложного, не так ли?

 

Спасибо за внимание! Подписывайтесь на рассылку 😉

Возникли вопросы, предложения, советы? Пишите в комментариях — вместе обсудим!

 

Ссылка на игру:

 

 

Поиграть тут:

 

 

Автор статьи: Alex. Категория: JavaScript
Дата публикации: 30.04.2013