Как создать текстовую приключенческую игру на Python

Короткая игра в формате «текстовой квест» — отличный проект для обучения программированию. Скрипт запускается в командной строке и изменяет ход истории в ответ на ввод игрока. В процессе вы практикуете print, условия, циклы, функции и простое управление состоянием.
Что важно знать перед началом
- Определение: текстовая приключенческая игра — интерактивная история, где игрок вводит команды (напр., “left”, “fight”) и получает текстовую реакцию.
- Язык: пример написан на Python 3. Рекомендуется использовать Python 3.7+.
- Кодировка: сохраняйте файл в UTF-8, чтобы корректно отображать русские тексты.
Важно: на Windows может понадобиться установить кодировку терминала командой chcp 65001 перед запуском для корректного вывода UTF-8.
Структура скрипта и ключевые элементы
Хорошая текстовая игра обычно строится из:
- Главной функции запуска (main). Она приветствует игрока и вызывает стартовую сцену.
- Набора функций-сцен (introScene, cameraScene и т.д.). Каждая функция отвечает за одну «комнату» или эпизод.
- Глобального состояния (переменные, словари, инвентарь), доступного разным сценам.
- Обработки ввода: нормализация (lower/strip), проверка валидных опций и повторный запрос на ошибочный ввод.
Ниже — полный пример скрипта, объединяющий все описанные сцены. Код прост для чтения и легко расширяется.
Полный пример кода
# AdventureGame.py
# Простой текстовый квест на Python
import sys
weapon = False # глобальная переменная-индикатор найденного оружия
def introScene():
directions = ["left", "right", "forward", "backward"]
print("Вы на перекрёстке катакомб. Куда пойдёте?")
userInput = ""
while userInput not in directions:
print("Варианты: left/right/forward/backward")
userInput = input().lower().strip()
if userInput == "left":
showShadowFigure()
elif userInput == "right":
showSkeletons()
elif userInput == "forward":
hauntedRoom()
elif userInput == "backward":
print("Дверь ведёт в стену. Нечего здесь делать.")
else:
print("Введите допустимый вариант для игры.")
def showShadowFigure():
directions = ["right", "backward"]
print("Вдалеке появляется тёмная фигура. Вас это пугает. Куда идти?")
userInput = ""
while userInput not in directions:
print("Варианты: right/backward")
userInput = input().lower().strip()
if userInput == "right":
cameraScene()
elif userInput == "backward":
introScene()
else:
print("Введите допустимый вариант для игры.")
def cameraScene():
directions = ["forward", "backward"]
print("На земле лежит фотоаппарат — кто-то был здесь недавно. Куда?")
userInput = ""
while userInput not in directions:
print("Варианты: forward/backward")
userInput = input().lower().strip()
if userInput == "forward":
print("Вы нашли выход! Поздравляем.")
sys.exit(0)
elif userInput == "backward":
showShadowFigure()
else:
print("Введите допустимый вариант для игры.")
def hauntedRoom():
directions = ["right", "left", "backward"]
print("Вы слышите странные голоса. Что будете делать?")
userInput = ""
while userInput not in directions:
print("Варианты: right/left/backward")
userInput = input().lower().strip()
if userInput == "right":
print("Из тьмы выходят существа. Вас убивают.")
sys.exit(0)
elif userInput == "left":
print("Вы нашли выход! Поздравляем.")
sys.exit(0)
elif userInput == "backward":
introScene()
else:
print("Введите допустимый вариант для игры.")
def showSkeletons():
global weapon
directions = ["left", "forward", "backward"]
print("Стена из скелетов. Кто-то наблюдает. Куда пойдёте?")
userInput = ""
while userInput not in directions:
print("Варианты: left/forward/backward")
userInput = input().lower().strip()
if userInput == "left":
print("Вы обнаруживаете нож за гипсокартоном. Вы берёте его.")
weapon = True
elif userInput == "backward":
introScene()
elif userInput == "forward":
strangeCreature()
else:
print("Введите допустимый вариант для игры.")
def strangeCreature():
global weapon
actions = ["fight", "flee"]
print("Появилось существо. Бежать или сражаться?")
userInput = ""
while userInput not in actions:
print("Варианты: fight/flee")
userInput = input().lower().strip()
if userInput == "fight":
if weapon:
print("Вы убили существо ножом и нашли выход. Поздравляем!")
sys.exit(0)
else:
print("Без оружия вы не выдержали. Вас убили.")
sys.exit(0)
elif userInput == "flee":
showSkeletons()
else:
print("Введите допустимый вариант для игры.")
if __name__ == "__main__":
while True:
print("Добро пожаловать в Adventure Game!")
print("Вы — путешественник, решивший исследовать катакомбы Парижа.")
print("Во время исследования вы потерялись и теперь должны выбрать путь.")
print("Начнём с вашего имени:")
name = input().strip()
print(f"Удачи, {name}.")
introScene()Примечание: код использует input().lower().strip(), чтобы принять ввод независимо от регистра и лишних пробелов.

Пояснения к коду и улучшения
- Нормализация ввода: всегда приводите ввод к нижнему регистру и обрезайте пробелы. Это снижает число неожиданных ответов.
- Управление состоянием: если игра растёт, замените глобальные переменные на словарь состояния (state = {“weapon”: False, …}). Это упростит сохранение/загрузку.
- Завершение: sys.exit(0) — явный выход. В больших проектах полезнее возвращать коду результата или использовать цикл игры с состоянием “running”.
- Проверки: вынесите валидацию ввода в вспомогательную функцию, чтобы избежать дублирования.
Пример функции-помощника для ввода:
def get_choice(prompt, valid):
while True:
print(prompt)
choice = input().lower().strip()
if choice in valid:
return choice
print("Недопустимый вариант. Повторите ввод.")Использование get_choice делает сцены короче и чище.
Расширения, которые стоит добавить
- Инвентарь: словарь предметов и их свойств.
- Сохранение/загрузка: сериализация состояния в JSON.
- Система диалогов: шаблоны для выбора вариантов с последствиями.
- Случайные события: модуль random для непредсказуемости.
- Тесты: модуль unittest с имитацией ввода (monkeypatch input).
- Многоязычность: отдельный файл строк (JSON/YAML) для локализации.
Важно: при добавлении «случайности» документируйте вероятности и их влияние на баланс игры.
Краткая методология: как развивать игру от MVP до версии 1.0
- MVP (минимально работоспособный продукт): одна карта сцен, базовый ввод, 2–3 концовки.
- Версия 0.5: добавить инвентарь, несколько предметов и пару новых ветвей.
- Версия 1.0: интерфейс сохранения, тесты, документация сцен, лог ошибок.
Малые шаги и частые прогонные тесты помогут избежать большого рефакторинга.
Когда такой подход не подойдёт (контрпримеры)
- Если нужна графика или звук — текстовый движок не даст нужного опыта.
- Для многопользовательской игры лучше серверная архитектура.
- Для сложной нелинейности и большого объёма контента стоит использовать специализированные движки (Ren’Py, Twine) или сериализацию сценариев.
Тестовые сценарии и критерии приёмки
Критерии приёмки:
- Игра запускается командой python AdventureGame.py без ошибок.
- Все указанные опции корректно обрабатываются (left/right/forward/backward/fight/flee).
- Наличие хотя бы двух разных финалов (выход/смерть).
- Состояние оружия корректно влияет на исход боя.
Тестовые случаи:
- Ввод «left» → showShadowFigure → «right» → cameraScene → «forward» → выход.
- Ввод «right» → showSkeletons → «left» → weapon=True → «forward» → strangeCreature → «fight» → выход.
- Попытка ввести недопустимое значение: игра просит повторить ввод.
Чек-листы по ролям
Разработчик:
- Подключить обработку ошибок и нормализацию ввода.
- Вынести повторяющуюся логику в функции.
- Написать unit-тесты для ключевых путей.
Сценарист:
- Спроектировать map/flow сцен заранее.
- Убедиться, что варианты описаны однозначно.
- Подготовить локализацию строк.
Тестировщик:
- Проверить все ветви сценария.
- Проверить сохранение/загрузку (если реализовано).
- Проверить поведение при неверном вводе.
Диаграмма принятия решений (Mermaid)
flowchart TD
Start[Старт] --> Intro
Intro -->|left| Shadow
Intro -->|right| Skeletons
Intro -->|forward| Haunted
Shadow -->|right| Camera
Camera -->|forward| Exit
Camera -->|backward| Shadow
Skeletons -->|left| GetKnife
GetKnife --> Skeletons
Skeletons -->|forward| Creature
Creature -->|fight с ножом| Exit
Creature -->|fight без ножа| Death
Creature -->|flee| Skeletons
Haunted -->|left| Exit
Haunted -->|right| Death
Haunted -->|backward| IntroЛокализация и особенности для русскоязычной аудитории
- Текстовые строки переводите в отдельный файл (locale/ru.json). Это упростит поддержку и добавление других языков.
- Убедитесь, что терминал поддерживает UTF-8. На Windows иногда требуется chcp 65001.
- Если игра планируется распространяться, помните о культурных нюансах описаний и сцен.
Шаблон простого файла локализации (JSON)
{
"welcome": "Добро пожаловать в Adventure Game!",
"choose_direction": "Варианты: left/right/forward/backward",
"invalid": "Введите допустимый вариант для игры."
}Практические советы по UX текста
- Пишите короткие предложения. Они легче читаются в терминале.
- Показывайте доступные опции отдельно от описания сцены.
- Даёте игроку понятный фидбек при неверном вводе.



Резюме
Создание текстовой приключенческой игры на Python — быстрый и полезный проект для обучения. Начните с простого скрипта, используйте функции для сцен и глобальное (или централизованное) состояние для предметов. Затем добавляйте инвентарь, сохранение, локализацию и тесты. Планируйте сюжет заранее и защищайте ввод пользователя. Минимальный рабочий пример легко превратить в полноценную игру с ветвлениями, случайными событиями и более богатым интерфейсом.
Важно: перед публикацией протестируйте все основные ветви и убедитесь, что локализация и кодировка корректно настроены.
Ключевые шаги для старта: создать файл AdventureGame.py, вставить пример кода, запустить python AdventureGame.py и воспроизвести ключевые сценарии.
Похожие материалы
Выбор структуры данных: практическое руководство
Как полностью покинуть iCloud и экосистему Apple
Отключить отслеживание Facebook — Off‑Facebook Activity
Как публиковать несколько BeReal в один день
Партнёрские программы для блога — настройка и рост