····elif ["$guess" = "quit"]; then # Запрошен выход? Хорошо.
······exit 0
····# Теперь нужно проверить присутствие введенной буквы в слове.
····elif [$(echo $guess | wc −c | sed 's/[^[: digit: ]]//g') −ne 2]; then
······echo "Uh oh: You can only guess a single letter at a time"
····elif [! -z "$(echo $guess | sed 's/[[: lower: ]]//g')"]; then
······echo "Uh oh: Please only use lowercase letters for your guesses"
····elif [-z "$(echo $guess | sed "s/[$empty$guessed]//g")"]; then
······echo "Uh oh: You have already tried $guess"
····# Теперь можно проверить присутствие буквы в слове.
····elif ["$(echo $match | sed "s/$guess/-/g")"!= "$match"]; then
······guessed="$guessed$guess"
······partial="$(echo $match | sed "s/[^$empty${guessed}]/-/g")"
······if ["$partial" = "$match"]; then
········echo "** You've been pardoned!! Well done! The word was \"$match\"."
········guess="$match"
······else
········echo "* Great! The letter \"$guess\" appears in the word!"
······fi
····elif [$bad −eq 1]; then
······echo "** Uh oh: you've run out of steps. You're on the platform…"
······echo "** The word you were trying to guess was \"$match\""
······guess="$match"
····else
······echo "* Nope, \"$guess\" does not appear in the word."
······guessed="$guessed$guess"
······bad=$(($bad — 1))
····fi
··done
done
exit 0
Все проверки в этом сценарии достаточно интересны, чтобы исследовать их подробнее. Взгляните на строку
, которая проверяет, не ввел ли пользователь больше одного символа.
Почему в сравнении используется число 2, а не 1? Потому что к предложенной пользователем букве в результате нажатия клавиши Enterдобавляется символ перевода строки (\n). То есть правильно, когда строка содержит два символа, а не один. Команда sed в этой инструкции отбрасывает все нецифровые символы, чтобы исключить любые проблемы с начальными символами табуляции, которые так любит добавлять команда wc.
Проверка принадлежности к нижнему регистру в строке
проста и понятна. Здесь удаляются все буквы нижнего регистра, и результат проверяется на равенство пустой строке.
Наконец, чтобы увидеть, предлагал ли уже пользователь эту букву: содержимое guess преобразуется так, что из него удаляются все буквы, присутствующие в переменной guessed. Затем проверяется, получилась ли в результате пустая строка
.
Кроме всех этих проверок в сценарии hangman используется еще одна хитрость: в исходном слове все буквы, совпадающие с введенной, заменяются дефисами. Затем результат сравнивается с исходным словом
. Если они различаются (то есть если одна или несколько букв заменены дефисами), значит, предложенная пользователем буква есть в слове. Например, если для загаданного слова cat пользователь ввел букву a , она будет записана в переменную guessed, которая получит значение '-a-'.
Одна из ключевых идей, лежащих в основе сценария hangman, — вывод частично угаданного слова из переменной partial, значение которой повторно собирается с каждой угаданной буквой. Поскольку в переменной guessed накапливаются буквы, угаданные игроком, команда sed преобразует в дефисы все буквы в исходном слове, которые отсутствуют в строке guessed
.
Игра «виселица» принимает один необязательный аргумент: переданное ей число используется как максимально допустимое число ошибочных попыток, в противном случае их будет шесть (значение по умолчанию). В листинге 12.4 демонстрируется пример запуска сценария hangman без аргументов.
Листинг 12.4.Сеанс игры «виселица»
$ hangman
steps from gallows: 6, word so far: —-
Guess a letter: e
* Great! The letter "e" appears in the word!
guessed: e, steps from gallows: 6, word so far: −e-e-
Guess a letter: i
* Great! The letter "i" appears in the word!
guessed: ei, steps from gallows: 6, word so far: −e-e-i-
Guess a letter: o
* Great! The letter "o" appears in the word!
guessed: eio, steps from gallows: 6, word so far: −e-e-io-
Guess a letter: u
* Great! The letter "u" appears in the word!
guessed: eiou, steps from gallows: 6, word so far: −e-e-iou-
Guess a letter: m
* Nope, "m" does not appear in the word.
Читать дальше