Выбрать главу

······else

········echo "Nope. That's not the unscrambled word. Try again."

········guesses=$(($guesses + 1))

······fi

····done

··done

··echo "Done. You correctly figured out $correct out of $total scrambled words."

··exit 0

Как это работает

Для выбора случайной строки из файла используется randomquote (сценарий № 68 из главы 8) , несмотря на то что первоначально этот сценарий был написан для работы с веб-страницами (многие хорошие утилиты Unix оказываются полезными в контекстах, отличных от тех, для которых они создавались).

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

Обратите внимание на местоположение $scrambled в двух строках: в первой следующая буква добавляется в конец $scrambled, а во второй — в начало.

В остальном логика игры должна быть понятна: внешний цикл until выполняется, пока пользователь не введет слово quit в качестве ответа, а внутренний цикл while выполняется, пока пользователь не угадает слово или не введет next, чтобы перейти к следующему слову.

Запуск сценария

Этот сценарий не имеет аргументов, так что просто введите его имя в командной строке и начните игру!

Результаты

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

Листинг 12.2. Запуск игрового сценария unscramble

$ unscramble

Picked out a word!

You need to unscramble: ninrenoccg

Your guess (quit|next): concerning

*** You got it with tries = 1! Well done!! ***

Picked out a word!

You need to unscramble: esivrmipod

Your guess (quit|next): quit

The unscrambled word was "improvised". Your tries: 0

Done. You correctly figured out 1 out of 2 scrambled words.

Первая же попытка оказалась успешной, и это вдохновляет!

Усовершенствование сценария

Вывод подсказки, хоть в каком-нибудь виде, сделал бы игру более интересной, также пригодился бы флаг, позволяющий ограничивать минимальную длину слова. В первом случае можно было бы за определенные штрафные очки показывать первые n букв из исходного слова и в ответ на каждый запрос подсказки добавлять еще одну букву. Для второго случая необходимо расширить словарь, так как предлагаемый вместе со сценарием содержит слова не короче 10 букв — хитро!

№ 84. Виселица: угадай слово, пока не поздно

Несмотря на жутковатую идею, игра в «виселицу» давно стала классикой. Вы пытаетесь угадать, какие буквы есть в задуманном слове, и каждый раз, когда вы ошибаетесь, у человечка на виселице дорисовывается очередная часть тела. Когда ошибок оказывается слишком много, появляется полное изображение, что означает проигрыш и… как вы понимаете, смерть человечка. Довольно безжалостная игра!

Однако сама по себе игра довольно забавная, а ее реализация в виде сценария командной оболочки оказывается на удивление простой, как демонстрирует листинг 12.3. Вам также потребуется список слов, использовавшийся в сценарии № 83: сохраните файл long-words.txt из ресурсов книги в каталоге /usr/lib/games.

Код

Листинг 12.3. Игровой сценарий hangman

#!/bin/bash

# hangman — простая версия игры "виселица". Вместо постепенного рисования

#·· человечка он просто ведет обратный отсчет ошибочных попыток.

#·· В единственном необязательном аргументе сценарий принимает начальное

#·· расстояние до эшафота.

wordlib="/usr/lib/games/long-words.txt"

empty="\." # Нам нужно что-то для sed [set], когда $guessed="".

games=0

# Сначала проверить наличие библиотеки слов — файла wordlib.

if [! -r "$wordlib"]; then

··echo "$0: Missing word library $wordlib" >&2

··echo "(online: http://www.intuitive.com/wicked/examples/long-words.txt" >&2

··echo "save the file as $wordlib and you're ready to play!)" >&2

··exit 1

fi

# Большой цикл while. Здесь все и происходит.

while ["$guess"!= "quit"]; do

··match="$(randomquote $wordlib)" # Выбрать новое слово из библиотеки.

··if [$games −gt 0]; then

····echo ""