к длине загаданного слова. Эта переменная понадобится, чтобы отсле-
живать количество букв, которые осталось угадать. Каждый раз, когда
игрок угадает букву, мы будем декрементировать (то есть уменьшать)
значение этой переменной: на 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 —
здесь «Виселица»
Виселица!
// Создаем массив со словами
var words = [
"программа",
"макака",
"прекрасный",
"оладушек"
];
// Выбираем случайное слово
var word = words[Math.floor(Math.random() * words.length)];
// Создаем итоговый массив
var answerArray = [];
for (var i = 0; i < word.length; i++) {
answerArray[i] = "_";
}
var remainingLetters = word.length;
// Игровой цикл
while (remainingLetters > 0) {
// Показываем состояние игры
alert(answerArray.join(" "));
122 Часть I. Основы
// Запрашиваем вариант ответа
var guess = prompt("Угадайте букву, или нажмите Отмена для
выхода из игры.");
if (guess === null) {
// Выходим из игрового цикла
break;
} else if (guess.length !== 1) {
alert("Пожалуйста, введите одиночную букву.");
} else {
// Обновляем состояние игры
for (var j = 0; j < word.length; j++) {
if (word[j] === guess) {
answerArray[j] = guess;
remainingLetters--;
}
}
}
// Конец игрового цикла
}
// Отображаем ответ и поздравляем игрока
alert(answerArray.join(" "));
alert("Отлично! Было загадано слово " + word);
Если игра не запускается, проверьте, все ли вы ввели правильно.
Обнаружить ошибки вам поможет JavaScript-консоль. Например, если
вы сделали опечатку в имени переменной, в консоли появится сооб-
щение с указанием, в какой строке ошибка, — примерно такое, как