Поиск

Упражнение: еще одна игра —лабиринт

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

Игра создана по образу и подобию классических игр — задача состоит в том, чтобы найти выход из лабиринта. Собственно лабиринт будет очень простым — он состоит из комнат с одной или несколькими дверями. Двери могут располагаться во всех четырех стенах комнаты (в северном, южном, восточном и западном направлениях). Цель игры — найти секретную комнату, к которой ведет только один правильный путь. Остальные пути ведут в тупик.

Итак, наберите в текстовом редакторе программу, приведенную в листинге 13.1, и сохраните ее в файле под именем Maze. Запустите программу и сыграйте с компьютером в игру, как показано в листинге 13.2.


Проведем анализ программы.

  • Строки 1-2. С этих двух строк начинается практически любая программа на Perl. Ключ -w активизирует режим вывода предупреждений, а оператор use strict используется для ужесточения контроля интерпретатора Perl над ошибками в программе и выявления плохого стиля программирования.
  • Строки 4—9. Здесь определяется структура Omaze, которая описывает лабиринт. Она представляет собой двумерный массив размером 4x4, реализованный в виде списка списков. Каждый элемент этого массива определяет положение дверей в соответствующей комнате лабиринта. Поэтому, если вы собираетесь изменить структуру лабиринта, позаботьтесь о том, чтобы из него был хотя бы один выход. В данном случае структура лабиринта выглядит так:

    В одну из комнат (2,1) попасть невозможно, поэтому она отмечена знаком - в структуре @maze. На самом деле для этих целей можно использовать любой символ, кроме с, п, з, в.

  • Строки 10-11. При движении игрока в одном из четырех направлений соответствующим образом должны изменяться его текущие координаты. Поэтому для вычисления нового положения игрока, в зависимости от его текущих координат и направления движения, используется хэш %direction. Например, при перемещении на "север" необходимо вычесть 1 из координаты х игрока, а его координату у оставить без изменений. При движении на "восток" координата х остается без изменений, а координата у увеличивается на 1. (Начало координат находится в левом верхнем углу лабиринта. Ось х направлена вниз, а ось у — вправо.) Изменение координат выполняется в строках 33 и 34 программы.
  • Строки 12—15. В этих строках с помощью операторату описываются переменные, используемые в программе. Явного описания переменных требует оператор use strict. Текущее положение игрока хранится в переменных $cur_х и Scur_y, а его начальная позиция равна (0,0). Конечное положение игрока (3,3) хранится в переменных $х и $у.
  • Строка 17. Эта подпрограмма отображает возможные направления движения игрока в зависимости от его положения (координат х и у).
  • Строка 20. Из массива описания лабиринта @maze выбираются коды разрешенных направлений движения для текущей комнаты ($maze[$cx][$cyj). Затем из кода направления в цикле выделяются буквы, соответствующие сторонам света (с, о, з, в), полное описание которых хранится в хэше %full. Этот хэш используется только для преобразования кодов направлений (с) в название стороны света (север) и отображения его на экране монитора.
  • Строка 25. Функции move_to передаются код направления (он сохраняется в переменной $new) и ссылки на текущие координаты игрока.
  • Строка 28. Код направления преобразовывается к нижнему регистру с помощью функции 1с, а функция substr выделяет первый символ из введенного пользователем кода направления. Результат снова присваивается переменной $new. Например, если пользователь введет Восток, переменной $new присваивается значение в, Запад — з и т.д.
  • Строка 29. Введенный пользователем код сравнивается с кодами возможного направления движения из текущей комнаты ($maze[$$xref] [$$yref]). При несовпадении выводится сообщение об ошибке.
  • Строки 33—34. Выполняется изменение текущих координат х и у пользователя. Например, если был введен код направления в, из элемента хэша $direction{B} выбирается ссылка на двухэлементный массив (0, 1). В результате к текущей координате х прибавляется значение 0 — $direction{B}[0], a значение координаты у увеличивается на 1 — $direction{B}[l].
  • Строка 37. В этой строке начинается тело основной программы. Цикл продолжается до тех пор, пока текущие координаты пользователя ($curr_x и $curr_y) не сравняются с координатами $х и $у секретной комнаты.
  • Строка 38. Отображается "план" текущей комнаты.
  • Строки 39—41. Введенный пользователем код направления движения считывается в переменную $move, после чего с помощью функции chomp из нее удаляется символ перевода строки. Если пользователь введет символ q, игра завершается.
  • Строка 42. Вызывается подпрограмма moveto, которой передаются код направления движения и ссылки на текущие координаты игрока. Эта подпрограмма выполняет пересчет текущих координат игрока $curr_x и $curr_y в зависимости от введенного кода направления.

Чтобы задать другую конфигурацию лабиринта, просто измените значения элементов массива @maze. Обратите внимание, что форма лабиринта не обязательно должна быть квадратной. Не обязательно также определять возможные направления движения из каждой комнаты, как и не обязательно, чтобы вообще существовал выход из лабиринта. Однако в комнатах не должно существовать дверей, ведущих наружу лабиринта. Учтите, что в программе не проверяется правильность построения лабиринта, хотя Perl выводит предупреждения, если вы неправильно зададите значения элементов массива Omaze. Координаты секретной комнаты хранятся в переменных $х и $у. Измените их, если хотите переместить конечную точку лабиринта в другое место.