Views Comments Previous Next Search

Я пишу текстовую игру на Python: первый прототип

 В новом выпуске блога о программировании я довожу игру LAM-40 (мы начали писать её в позапрошлом выпуске) до элементарного прототипа, который уже можно испытывать.

Я пишу текстовую игру на Python: первый прототип. Изображение № 1.

Предыдущий выпуск

Я учусь программировать
на Python: установка

 

Я пишу текстовую игру на Python: первый прототип. Изображение № 2.

В прошлый раз мы разобрались, как подготовить компьютер к работе с Python, и теперь можем перейти к написанию игры. В создании любой игры чуть ли не самое важное — это как можно скорее начать её прототипировать, чтобы сразу выявить основные уязвимости и устранить их. У нас, конечно, игра довольно простая, да и главное для нас не её качество, а упражнения с кодом. Тем не менее раннее прототипирование — это полезная привычка в разработке чего угодно, поэтому давайте ей следовать.

Для тех, кто успел подзабыть за две недели суть того, что мы делаем, напомню. LAM-40 — это текстовая игра, где вы играете за человека, которому нужно успеть за девять часов получить справку на 40-м этаже загадочного государственного учреждения, переполненного бюрократами. Каждый этаж учреждения генерируется случайным образом: игроку попадаются бюрократы разного уровня, к каждому из которых нужно искать особый подход, чтобы пройти дальше и добраться до последнего этажа.

Примечание: весь код приводится для Python версии 3.0 и старше, а потому может не работать на более старых версиях.

   

Для начала давайте вспомним, какой код остался у нас с прошлого раза, и разберёмся, чем мы его хотим дополнить.

У нас есть простенький класс бюрократа, умеющего здороваться с игроком и обладающего двумя характеристиками — рангом и настроением. Задача на сегодня — создать простейший, бесконечно повторяющийся цикл «сражений» с бюрократами, что, по сути, и есть основная механика нашей игры. Получившийся у меня в итоге прототип занял 95 строк — начнём его разбирать по порядку (последняя пустая строка должна быть по стандартам PEP 8, но embed'ы её обрубают).

  Строка 2: помимо random, в начале программы мы импортируем модуль sys. Из него нам понадобится функция exit() — возможность выйти из игры, пока что не указанная эксплицитно.

  Строки 5–13, 16: я добавил списки положительных и отрицательных реакций бюрократов. Обратите внимание, как используются переносы. Дело в том, что, согласно PEP 8, максимальная длина строки должна быть 79 символов, иначе код будет слишком сложно читать. Именно поэтому для удобства каждое новое высказывание находится на новой строке и написано с тем же отступом, что и предыдущее. Ещё я добавил переменную ACTIONS типа данных string с основными действиями игрока (обычным вопросом, подкупом, мольбой, давлением и угрозой), чтобы не делать слишком длинной строку, где мы будем выводить все эти действия.

  Строки 25, 34–44: у класса Bureaucrat появилась характеристика negative логического типа данных (то есть истина или ложь) со значением False. Она показывает, был ли ход игрока удачным — если нет, то её значение становится True, и игра предлагает нам совершить новое действие на том же самом бюрократе, а не создаёт нового бюрократа. Для того чтобы отобразить реакцию бюрократа на действие игрока, используются функции с говорящими названиями react_positively() и react_negatively(), которые меняют значение переменной negative и выводят случайную реакцию бюрократа на случившееся.

  Строки 46–85: функция act() выводит на экран все возможные действия игрока и предлагает ему выбрать одно из них, введя первую букву слова. Именно для того, чтобы не загружать эту строку, мы вывели string со всеми действиями в отдельную переменную ACTIONS. Следом за этим идёт ветвление, и мы впервые в этом блоге используем ключевое слово elif — сокращение от else if. Оно задаёт условие помимо того, что указано в if, а блок с ним — следующие за выполнением этих условий действия. В нашем случае мы проверяем, что ввёл игрок. Если он ввёл строчную букву Q, выполнение программы завершится из-за упомянутой ранее функции sys.exit(). Если игрок введёт строчную букву W (wait), то ему выпадет новый бюрократ — это тоже пока что незадокументированная возможность. Если же игрок введёт какой-нибудь другой символ, то программа перейдёт в функцию react(), где ветвление выходит на новый уровень. На текущем этапе я сделал так, что для определённых сочетаний ранга и настроения бюрократа срабатывает лишь одно действие. Более того, есть непобедимые сочетания (например, высокий ранг и плохое настроение), в случае с которыми приходится вводить W, чтобы выпал следующий бюрократ.

  Самая большая головная боль на первых порах — это использование ключевого слова self, когда вы ссылаетесь на функцию или характеристику класса внутри этого класса, и оператора сравнения == вместо оператора присваивания = рядом с условными операторами. Вероятно, и о том, и о другом вы будете забывать, так что следите за этим. Кстати, обратите внимание на ключевое слово and, которое используется рядом с операторами ветвления — оно обозначает, что должны выполняться оба условия, находящиеся рядом с ним.

  Строки 87–94: наконец, в самом низу заканчивается описание класса и начинается логика основной программы. Мы создаём образец класса Bureaucrat, присваиваем его переменной bureaucrat и используем функцию с приветствием бюрократа. После этого запускаем бесконечный цикл, внутри которого запускаем функцию с выводом и вводом действий игрока, а также условное исполнение создания и приветствия нового бюрократа — в зависимости от того, каково текущее значение bureaucrat.negative. Обратите внимание на две вещи: оператор else при желании можно не использовать, а в случае с логическими типами данных в Python вместо оператора == применяют ключевое слово is.

   

Первый прототип LAM-40 готов. Конечно, он ещё далёк не то что от финальной, а даже от альфа-версии, поэтому нам предстоит порядочно поработать. Сейчас я вижу кучу проблем с этим прототипом, которые собираюсь устранить в следующий раз:

  Нужно полностью изменить структуру кода: текстовые данные из верхней части перенести в отдельную базу, функции раскидать по другим классам, основную логику программы направить в отдельный файл и так далее.

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

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

  Желательно описывать текстом все действия, что возможны в игре, в том числе выход из неё и ожидание.

  Из возможных действий желательно сделать список, а не отдельный string, чтобы туда можно было при определённых условиях добавлять новые действия. Кроме того, на ввод нужно применить функцию upper(), чтобы не требовалось каждый раз вводить строчные буквы. Также надо сделать адекватную реакцию на неверно введённые символы.

  В основной логике игры есть повторяющиеся две строчки, нарушающие правило DRY. Да и сам цикл не очень красив — пожалуй, стоит над ним подумать, когда он начнёт расширяться.

  Куча мелочей вроде описания функции act(), комментариев к некоторым частям кода, использования sys.exit() и характеристики negative, которая тоже не очень изящное решение. Так что поищу ему альтернативу.

Как видите, работы предстоит полно. Надеюсь, к следующему разу игра примет уже более целостный вид. Если вам что-то непонятно, пишите комментарии под материалом и в социальных сетях — буду рад и любым другим отзывам. Если вы более опытный в программировании человек, чем я, то с удовольствием выслушаю содержательную критику. Спасибо, и до следующего раза!

Смотрите также:

  Полные курсы Python на Codeacademy и Treehouse*

* — платные курсы, но есть пробный период

  Развитие программистского мышления на Udacity

  Учебники по Python на LearnPython.org и Python Course

Рассказать друзьям
2 комментарияпожаловаться

Комментарии

Подписаться
Комментарии загружаются