JavaScript для детей — страница 21 из 48

к длине загаданного слова. Эта переменная понадобится, чтобы отсле-

живать количество букв, которые осталось угадать. Каждый раз, когда

игрок угадает букву, мы будем декрементировать (то есть уменьшать)

значение этой переменной: на 1 для каждого вхождения буквы в слово.

Программируем игровой цикл

Основа игрового цикла выглядит так:

while (remainingLetters > 0) {

// Основной код

// Показываем состояние игры

// Запрашиваем вариант ответа

// Обновляем answerArray и remainingLetters для каждого

// вхождения угаданной буквы

}

Мы используем цикл while, который будет повторяться

до тех пор, пока условие remainingLetters > 0 дает true.

В теле цикла надо будет обновлять remainingLetters

для каждого правильного ответа игрока; когда игрок уга-

дает все буквы, remainingLetters примет значение 0,

и цикл завершится.

Далее мы рассмотрим код, составляющий тело игро-

вого цикла.

Отображение состояния игры

Первым делом в теле игрового цикла нужно показать игроку текущее

состояние игры:

alert(answerArray.join(" "));

Мы делаем это, объединяя элементы answerArray в строку с про-

белом в качестве разделителя, а затем с помощью alertпоказываем

эту строку. Например, пусть загадано слово «макака» и игрок угадал

118 Часть I. Основы

буквы «м» и «а». Тогда итоговый массив примет вид: ["м", "а", " _ ",

"а", " _ ", "а"] и answerArray.join("") вернет строку "м а _ а _ а".

Диалог alert в этом случае будет выглядеть как на рис. 7.4.

Рис. 7.4. Отображение состояния игры с помощью alert

Обработка введенного ответа

Теперь нужно запросить у игрока ответ и убедиться, что он ввел одиноч-

ную букву.

 var guess = prompt("Угадайте букву или нажмите Отмена для выхода 

Guess —

из игры.");

предположе-

if (guess === null) {

ние

break;

 } else if (guess.length !== 1) {


Break — здесь

alert("Пожалуйста, введите только одну букву.");

«отмена»

} else {

 // Обновляем состояние игры

}

В строке  prompt запрашивает у игрока ответ и сохраняет его

в переменной guess. Далее возможен один из четырех вариантов разви-

тия событий.

Первый вариант — если игрок нажмет кнопку «Отмена», guess при-

мет значение null. Этот вариант мы проверяем в строке  командой

if (guess === null). Если это условие даст true, мы с помощью break

выйдем из цикла.

! Ключевое слово break можно использовать для немедленного выхода

из любого цикла, независимо от того, где именно внутри цикла это про-

исходит, или от того, выполняется ли на этот момент условие while .

Второй и третий варианты — игрок не ввел ничего либо ввел

несколько букв. Если он просто нажал «ОК», ничего не вводя, в guess

окажется пустая строка (""), а guess.length вернет 0. Если же игрок

ввел больше одной буквы, guess.length вернет число больше 1.

В строке  мы с помощью else if (guess.length !== 1) обрабаты-

ваем эти варианты, то есть проверяем, что guess содержит в точности

7. Пишем игру «Виселица» 119

одну букву. В противном случае мы отображаем диалог alert, глася-

щий: «Пожалуйста, введите только одну букву».

Четвертый вариант — игрок, как и положено, ввел одну букву. Тогда

мы должны обновить состояние игры — это происходит в строке ,

в секции else. Об этом пойдет речь ниже.

Обновление состояния игры

Если игрок ввел корректный ответ, мы должны обновить answerArray

согласно этому ответу. Для этого добавим в тело else такой код:

 for (var j = 0; j < word.length; j++) {

 if (word[j] === guess) {

answerArray[j] = guess;

 remainingLetters--;

}

}

В строке мы задали цикл for с новой переменной j, которая будет

менять значение от 0 до word.length, не включая само значение word.

length. (Мы назвали переменную j, поскольку имя i уже использо-

вано в предыдущем цикле for.) В этом цикле мы проверяем каждую

букву переменной word. Например, пусть в word находится строка

"оладушек". Тогда при первом повторе цикла, когда j равно 0, word[j]

вернет "о". При следующем повторе word[j] вернет "л", затем "а", "д",

"у", "ш", "е" и, наконец, "к".

В строке мы с помощью if (word[j] === guess) проверяем,

совпадает ли текущая буква (word[j]) с ответом игрока. Если это

так, мы обновляем итоговый массив, добавляя туда букву командой

answerArray[j] = guess. Для каждой буквы, совпадающей с отве-

том, мы обновляем соответствующую позицию итогового массива.

Этот код работает, поскольку переменную цикла j можно использовать

одновременно в качестве индекса в строке word и индекса в массиве

answerArray, как показано на рис. 7.5.

Индекс (j)

0 1 2 3 4 5 6 7

word

" о л а д у ш e к "

answerArray ["_", "_", "_", "_", "_", "_", "_", "_"]

Рис. 7.5. Один и тот же индекс можно использовать для word и answerArray Например, представим, что мы только начали игру и дошли до цикла

for в строке . Пусть загадано слово «программа», в guess находится

буква "р", а answerArray имеет вид:

120 Часть I. Основы

[" _ ", " _ ", " _ ", " _ ", " _ ", " _ ", " _ ", " _ ", " _ "]

При первом повторе for в строке  j равно 0, поэтому word[j] вер-

нет "п". Наш ответ (guess) — это "р", поэтому мы пропускаем команду

if в строке  (ведь условие "п" === "р" дает false). При следующем

повторе j равно 1, и word[j] вернет "р". Это значение совпадает с guess,

и срабатывает оператор if. Команда answerArray[j] = guess присваи-

вает элементу с индексом 1 (второй элемент) массива answerArray зна-

чение guess, и теперь answerArray имеет вид:

[" _ ", "р", " _ ", " _ ", " _ ", " _ ", " _ ", " _ ", " _ "]

При следующих двух повторах цикла word[j] вернет "о", а затем

"г", что не совпадает со значением guess. Однако когда j достигнет 4,

word[j] снова вернет "р". И снова мы обновим answerArray, на этот

раз присвоив значение guess элементу с индексом 4 (пятый элемент).

Теперь answerArray выглядит так:

[" _ ", "р", " _ ", " _ ", "р", " _ ", " _ ", " _ ", " _ "]

Оставшиеся буквы не совпадают с "р", так что при дальнейших

повторах ничего не произойдет. Так или иначе, после завершения цикла

в answerArray будут внесены все совпадения guess с соответствую-

щими позициями word.

Помимо обновления answerArray для каждого совпадения с guess

требуется уменьшать remainingLetters на 1. Мы делаем это в строке 

командой remainingLetters--;. Каждый раз, когда guess совпадает

с буквой из word, remainingLetters уменьшается на 1, и, когда игрок

угадает все буквы, remainingLetters примет значение 0.

Конец игры

Как мы знаем, игровой цикл while выполняется при условии

remainingLetters > 0, поэтому его тело будет повторяться до тех пор,

пока еще остаются неотгаданные буквы. Когда же remainingLetters

уменьшится до 0, цикл завершится. После цикла нам остается лишь

закончить игру — это позволяет сделать такой код:

alert(answerArray.join(" "));

alert("Отлично! Было загадано слово " + word);

7. Пишем игру «Виселица» 121

В первой строке мы последний раз отображаем итоговый мас-

сив. Во второй строке, опять же с помощью alert, мы поздравляем

игрока с победой.

Код игры

Итак, мы разобрали по частям весь код игры, осталось лишь

соединить все вместе. Ниже он приведен целиком, от начала

до конца. Я добавил в него комментарии, поясняющие, что про-

исходит в том или ином месте программы. Обязательно вручную

введите код в компьютер — это поможет вам поскорее набить

руку в JavaScript. Создайте новый файл под названием hangman.

html и введите в него следующее:

Hangman —

здесь «Виселица»

Виселица!

Виселица!

Если игра не запускается, проверьте, все ли вы ввели правильно.

Обнаружить ошибки вам поможет JavaScript-консоль. Например, если

вы сделали опечатку в имени переменной, в консоли появится сооб-

щение с указанием, в какой строке ошибка, — примерно такое, как