Python: Создание пошаговой CLI-стратегии управления миром

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

1. Основы Python и архитектура: настройка окружения, базовый синтаксис и создание главного игрового цикла

Основы Python и архитектура: настройка окружения, базовый синтаксис и создание главного игрового цикла

Создание текстовой стратегии (CLI — Command Line Interface) — это идеальный способ изучить программирование. Здесь нет отвлекающих факторов в виде сложной графики или физического движка. Есть только чистая логика, данные и архитектура. Мы создадим симулятор управления цивилизацией, где игрок принимает решения, управляет ресурсами и развивает свое государство, используя только текстовые команды.

Настройка рабочего окружения

Для начала работы нам потребуется интерпретатор Python и редактор кода. Python — это язык, который выполняет команды построчно, что делает его отличным выбором для быстрого прототипирования логики.

Установка Python

  • Перейдите на официальный сайт python.org.
  • Скачайте последнюю стабильную версию (3.10 или выше).
  • Важно: При установке на Windows обязательно поставьте галочку "Add Python to PATH". Это позволит запускать Python из командной строки.
  • Чтобы проверить установку, откройте терминал (Command Prompt или PowerShell) и введите:

    Если вы видите версию (например, Python 3.11.0), всё готово.

    Выбор редактора кода (IDE)

    Писать код в блокноте неудобно. Рекомендуется использовать специализированные среды разработки:

    * VS Code: Легкий, популярный, с огромным количеством плагинов. * PyCharm Community: Мощная среда, специально заточенная под Python, с отличным отладчиком.

    Создайте папку для проекта, например world_strategy, и откройте её в выбранном редакторе. Создайте файл main.py — это будет точка входа в нашу игру.

    Базовый синтаксис через призму игры

    Вместо абстрактных примеров мы сразу будем оперировать игровыми сущностями.

    Переменные и типы данных

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

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

    Ввод и вывод данных

    CLI-игра строится на диалоге с пользователем. Мы выводим информацию и запрашиваем команды.

    Для вывода используется функция print(). Самый удобный способ форматирования строк — f-strings (форматированные строки). Они позволяют встраивать значения переменных прямо в текст.

    Для получения данных от игрока используется функция input(). Она всегда возвращает строку, поэтому если мы ожидаем число, результат нужно преобразовать.

    Архитектура игрового цикла (Game Loop)

    Любая игра, от "Змейки" до Cyberpunk 2077, работает по одному и тому же принципу: бесконечный цикл, который обновляет состояние мира и отрисовывает его.

    !Классический паттерн Game Loop: Ввод -> Обновление -> Отрисовка

    В пошаговой стратегии цикл останавливается на этапе ввода, ожидая решения игрока. Как только решение принято, игра рассчитывает последствия, обновляет переменные и снова показывает состояние мира.

    Реализация цикла while

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

    Условные операторы if-elif-else

    В блоке Update мы используем ветвление. Python проверяет условия сверху вниз. * if: Начало проверки. * elif (else if): Дополнительная проверка, если предыдущая была ложной. * else: Выполняется, если ни одно из условий выше не сработало.

    Обратите внимание на отступы (indentation). В Python отступы (обычно 4 пробела) определяют вложенность кода. Это часть синтаксиса, а не просто стиль оформления.

    Математика игровой механики

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

    Формула прироста может выглядеть так:

    где — новое значение населения, — текущее население, — коэффициент рождаемости (например, 0.1 для 10%), а — округление вниз до целого числа.

    В коде это реализуется с помощью модуля math или встроенной функции int() для отбрасывания дробной части:

    Использование формул позволяет балансировать игру. Линейный рост (просто +5 каждый ход) скучен. Процентный рост (экспоненциальный) заставляет игрока инвестировать в базу как можно раньше.

    Структурирование кода: Функции

    Даже в простой игре код внутри while True быстро станет огромным и нечитаемым. Чтобы этого избежать, мы используем функции. Функция — это именованный блок кода, который можно вызывать многократно.

    Разделим нашу монолитную логику на логические блоки, соответствующие схеме Game Loop.

    Конструкция if __name__ == "__main__":

    Эта строка проверяет, запущен ли файл напрямую или импортирован как модуль. Это стандарт хорошего тона в Python. Она гарантирует, что игровой цикл запустится только тогда, когда вы явно запустите main.py.

    Обработка ошибок и валидация

    Игроки часто вводят не то, что вы ожидаете. Если вы ждете число, а игрок ввел букву, программа может упасть с ошибкой. В Python для перехвата ошибок используется конструкция try-except.

    Однако в нашем случае (меню выбора) достаточно строковой проверки через if/else. Но если мы захотим спросить "Сколько золота потратить?", нам потребуется проверка типа:

    Метод .isdigit() — это встроенный метод строк, который возвращает True, если строка состоит только из цифр.

    Итоги

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

  • Окружение: Python установлен, IDE настроена, проект создан.
  • Переменные: Мы используем int для ресурсов и str для команд.
  • Game Loop: Бесконечный цикл while True обеспечивает непрерывность игрового процесса.
  • Архитектура: Разделение на Ввод, Обновление и Отрисовку (Input-Update-Render) позволяет легко расширять игру.
  • Функции: Разбиение кода на функции main, print_state делает код чистым и поддерживаемым.
  • 2. Структуры данных и ООП: проектирование классов государств и управление ресурсами мира

    Структуры данных и ООП: проектирование классов государств и управление ресурсами мира

    В предыдущей части мы создали простой игровой цикл, используя отдельные переменные для золота, населения и номера хода. Этот подход работает для прототипа, но он совершенно непригоден для масштабирования. Представьте, что вы хотите добавить в игру компьютерного противника. Вам придется создавать переменные enemy_gold, enemy_population, enemy_turn. А если противников будет пять? Код превратится в хаос.

    Решением этой проблемы является Объектно-Ориентированное Программирование (ООП). Мы упакуем данные и логику в единую структуру — класс.

    Философия ООП: Чертеж и Здание

    Центральными понятиями ООП являются Класс и Объект (или Экземпляр).

    * Класс — это чертеж, шаблон или инструкция. Он описывает, какими свойствами должно обладать государство, но сам по себе государством не является. * Объект — это конкретное воплощение этого чертежа. По одному чертежу можно построить сотни домов. По одному классу State можно создать сотни государств.

    !Класс — это абстрактный чертеж, а объекты — конкретные реализации.

    Создание класса State

    В Python классы определяются ключевым словом class. Имена классов принято писать в стиле CamelCase (с большой буквы).

    Разберем этот код:

  • def __init__(self, name): — это специальный метод, называемый конструктором. Он запускается автоматически в момент создания нового объекта.
  • self — это ссылка на текущий создаваемый объект. Когда мы пишем self.gold = 100, мы говорим: «У этого конкретного государства золото равно 100».
  • Теперь мы можем создать сколько угодно стран:

    Структуры данных: Словари для ресурсов

    В стратегии количество типов ресурсов может расти. Сегодня у вас только золото, завтра — дерево, железо, мана и нефть. Создавать для каждого ресурса отдельное поле (self.wood, self.iron) неудобно.

    Лучше использовать словарь (dictionary). В Python это структура данных, хранящая пары «ключ — значение».

    Теперь, чтобы изменить количество дерева, мы обращаемся к словарю по ключу:

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

    Инкапсуляция логики: Методы класса

    В процедурном стиле (как в прошлой статье) мы меняли переменные напрямую в основном цикле. В ООП принято, чтобы объект сам управлял своим состоянием через методы (функции внутри класса).

    Перенесем логику производства ресурсов внутрь класса.

    Теперь в главном цикле игры нам не нужно знать формулу расчета налогов. Мы просто отдаем приказ: player.collect_tax().

    Математика производства

    Давайте усложним модель. Пусть производство зависит не только от населения, но и от эффективности управления. Формула дохода может выглядеть так:

    где — итоговый доход (Income), — население (Population), — базовая ставка налога (Rate), — коэффициент эффективности (Efficiency, например, 1.0 — норма, 1.2 — бонус).

    В коде это выглядит так:

    Списки: Управление зданиями

    Государство — это не только ресурсы, но и инфраструктура. Для хранения списка построенных зданий идеально подходит список (list). Это упорядоченная изменяемая коллекция элементов.

    Добавим список зданий в наш класс:

    Метод .append() добавляет элемент в конец списка. Теперь мы можем проверить наличие здания:

    Полный код обновленной архитектуры

    Теперь соберем все вместе. Мы заменим разрозненные переменные на объект класса State.

    Анализ изменений

  • Масштабируемость: Если мы захотим добавить второго игрока, нам достаточно написать enemy = State("Враг"). Вся логика налогов и голода для него уже написана внутри класса.
  • Читаемость: Главный цикл while стал чище. Детали расчетов спрятаны внутри методов update и print_status.
  • Гибкость: Использование словаря resources позволяет нам в будущем добавить ресурс "Мана", не переписывая половину кода, а просто добавив ключ в словарь.
  • Итоги

    Мы перешли от процедурного программирования к объектно-ориентированному, заложив мощный фундамент для развития игры.

  • Классы и Объекты: Класс — это шаблон, объект — конкретная сущность. self указывает на данные конкретного объекта.
  • Словари: Используйте словари {key: value} для хранения наборов данных (ресурсов), к которым нужен доступ по имени.
  • Списки: Используйте списки [] для хранения коллекций предметов (зданий, юнитов), порядок которых может иметь значение или которые нужно просто перечислять.
  • Инкапсуляция: Данные (золото, население) и методы работы с ними (сбор налогов) должны жить внутри одного класса.