Как создать игру «Виселица» на Python

Краткое введение
Виселица — классическая словесная игра, в которой игрок пытается угадать загаданное слово по буквам. Программа показывает дефисы вместо букв, иногда раскрывает одну-две буквы, а игрок отгадывает по одной букве. За каждую ошибку уменьшается число попыток, и по мере ошибок рисуется фигура висельника. В этом руководстве мы пошагово разберём простой реализационный вариант на Python и предложим идеи для улучшения и тестирования.
Как играть
Правила просты:
- Программа выбирает слово и показывает ряд символов “_” по количеству букв (иногда заранее раскрывается одна буква).
- Игрок вводит по одной букве.
- Если буква есть в слове — она становится видна в соответствующих позициях.
- Если буквы нет — уменьшается количество оставшихся попыток и докрашивается часть ASCII-фигуры.
- Если все буквы открыты — игрок победил. Если попытки закончились — проигрыш.
Важно: в предложенной реализации даётся 7 попыток (включая полную фигуру).
Структура проекта
Рекомендуемая минимальная структура файлов:
- hangman_wordlist.txt — текстовый файл со словами (по одному слову на строку).
- hangman.py — файл с реализацией игры.
Файл со словами может содержать имена, существительные, названия фильмов или любые другие слова. Вы можете собрать собственный список или использовать готовые словари.
Как это реализовано — пошагово
Ниже — пояснения к ключевым функциям и исходный код, приведённый в исходном материале. Я привожу код как есть, затем обсуждаю улучшения и локализацию интерфейса.
Выбор случайного слова
Функция получает случайное слово из файла со словами. Используется модуль random и чтение файла в режиме только для чтения.
import random
def get_random_word_from_wordlist():
wordlist = []
with open("hangman_wordlist.txt", 'r') as file:
wordlist = file.read().split("\n")
word = random.choice(wordlist)
return wordПояснения и советы:
- Метод with автоматически закрывает файл даже при ошибке.
- split(“\n”) разделяет строки, предполагая, что каждое слово — на отдельной строке.
- Если файл может содержать пустые строки, стоит дополнительно фильтровать пустые элементы: wordlist = [w.strip() for w in file.read().split(“\n”) if w.strip()].
Отображение начальных букв
Функция get_some_letters показывает строку из подчёркиваний и раскрывает одну случайную букву слова.
def get_some_letters(word):
letters = []
temp = '_' * len(word)
for char in list(word):
if char not in letters:
letters.append(char)
character = random.choice(letters)
for num, char in enumerate(list(word)):
if char == character:
templist = list(temp)
templist[num] = char
temp = ''.join(templist)
return tempСоветы:
- Функция защищает от повторных одинаковых символов, выбирая случайную букву из уникальных.
- Для слов с регистром стоит привести word к одному регистру (например, lower()) и затем показывать пользователю в выбранном регистре или нормализовать ввод.
Отрисовка виселицы
Функция draw_hangman печатает ASCII-арт в зависимости от числа оставшихся попыток.
def draw_hangman(chances):
if chances == 6:
print("________ ")
print("| | ")
print("| ")
print("| ")
print("| ")
print("| ")
elif chances == 5:
print("________ ")
print("| | ")
print("| 0 ")
print("| ")
print("| ")
print("| ")
elif chances == 4:
print("________ ")
print("| | ")
print("| 0 ")
print("| / ")
print("| ")
print("| ")
elif chances == 3:
print("________ ")
print("| | ")
print("| 0 ")
print("| /| ")
print("| ")
print("| ")
elif chances == 2:
print("________ ")
print("| | ")
print("| 0 ")
print("| /|\ ")
print("| ")
print("| ")
elif chances == 1:
print("________ ")
print("| | ")
print("| 0 ")
print("| /|\ ")
print("| / ")
print("| ")
elif chances == 0:
print("________ ")
print("| | ")
print("| 0 ")
print("| /|\ ")
print("| / \ ")
print("| ")Заметки:
- В Python строки с обратным слэшем в конце (например “\”) нужно экранировать (как в блоке выше: “\”). В оригинальном тексте уже учтено.
- Можно заменить серию if/elif на список строк и выбирать нужный индекс по количеству попыток — это упрощает поддержку.
Основная игровая петля
Ключевая функция start_hangman_game объединяет логику: выбор слова, показ начального состояния, приём ввода, проверка и обновление состояния.
def start_hangman_game():
word = get_random_word_from_wordlist()
temp = get_some_letters(word)
chances = 7
found = FalseОсновной цикл, обработка ввода и завершение игры:
while True:
if chances == 0:
print(f"Sorry! You Lost, the word was: {word}")
print("Better luck next time")
break
print("=== Guess the word ===")
print(temp, end='')
print(f"\t(word has {len(word)} letters)")
print(f"Chances left: {chances}")
character = input("Enter the character you think the word may have: ")
if len(character) > 1 or not character.isalpha():
print("Please enter a single alphabet only")
continueДальнейшая логика обновляет temp при совпадении, меняет found и уменьшает chances при ошибке. Когда в temp не остаётся подчёркиваний — игрок выиграл.
else:
for num, char in enumerate(list(word)):
if char == character:
templist = list(temp)
templist[num] = char
temp = ''.join(templist)
found = True
if found:
found = False
else:
chances -= 1
if '_' not in temp:
print(f"\nYou Won! The word was: {word}")
print(f"You got it in {7 - chances} guess")
break
else:
draw_hangman(chances)
print()Точка входа
Форма запуска игры и базовая обработка желания пользователя играть снова:
print("===== Welcome to the Hangman Game =====")
while True:
choice = input("Do you wanna play hangman? (yes/no): ")
if 'yes' in choice.lower():
start_hangman_game()
elif 'no' in choice.lower():
print('Quitting the game...')
break
else:
print("Please enter a valid choice.")
print("\n")Совет по локализации: строки приветствия и подсказки можно перевести на русский (например, “Хотите сыграть? (да/нет): “) — если вы меняете текстовую локализацию, не забудьте соответствующе обрабатывать ответы (например, искать “да”/“нет”).
Примеры вывода
Если вы выиграли, программа покажет открытое слово и поздравление.
Если вы проиграли, программа покажет завершённую ASCII-виселицу и сообщение о поражении.
Улучшения и альтернативные подходы
Ниже — идеи для развития проекта, которые делают игру интереснее и надёжнее.
- Локализация интерфейса: перевод подсказок и сообщений, поддержка кириллицы в словаре.
- Поддержка нечувствительности к регистру: приводите ввод и слово к lower() при сравнении.
- Сохранение истории и статистики: количество игр, побед/поражений, среднее число угадываний.
- Расширенная визуализация: использование curses для терминала или Pygame/GUI для графики.
- Поддержка многопользовательского режима: первый игрок вводит слово, второй отгадывает.
- Защита от некорректных слов в словаре: фильтрация по длине, отсутствие специальных символов.
Когда этот подход не подходит
- Если вам нужен кросс-платформенный GUI с кнопками и анимацией — лучше использовать Pygame или фреймворк GUI.
- Если необходимо играть в браузере — реализуйте игру на JavaScript и HTML/CSS.
- Для больших словарей (миллионы слов) чтение всего файла в память может быть неэффективно — используйте выбор по смещению в файле или базу данных.
Ментальные модели и эвристики при доработке
- Разделяй обязанности: ввод/вывод — интерфейсный слой, логика игры — отдельные функции, доступ к словарю — отдельный модуль.
- Минимизируй состояние: храните только необходимое (слово, текущее отображение, оставшиеся попытки, набор угаданных букв).
- Валидируй ввод на каждом шаге и давайте пользователю понятные подсказки.
Мини-методология разработки (быстрый план)
- Написать функцию чтения слов из файла и тестировать её.
- Реализовать основную игровую логику (проверка букв, обновление состояния).
- Сделать функцию отрисовки ASCII-виселицы.
- Добавить обработку ввода и валидацию.
- Добавить тесты — юнит-тесты для функций, сценарные тесты для игровой петли.
- Оптимизировать и локализовать интерфейс.
Критерии приёмки
- Игра корректно выбирает слово из файла и не падает на пустых строках.
- При вводе одной корректной буквы состояние обновляется верно.
- При вводе неалфавитных символов или более одной буквы — выводится понятная ошибка и игра не рушится.
- Игра корректно определяет победу и поражение и рисует соответствующую ASCII-виселицу.
Тестовые случаи
- Ввод неалфавитного символа: программа предупреждает и просит повторить ввод.
- Ввод нескольких символов: программа предупреждает и просит повторить ввод.
- Угадать слово полностью: программа сообщает о победе и корректно подсчитывает число попыток.
- Израсходовать все попытки: программа объявляет поражение и показывает слово.
- Слово с повторяющимися буквами: при вводе буквы все позиции раскрываются.
- Пустые строки в словаре: не должны приводить к выбору пустого слова.
Чек-лист для релиза
- Проверить словарь на пустые строки и спецсимволы.
- Добавить обработку EOFError и KeyboardInterrupt, чтобы корректно выходить.
- Локализовать строки и протестировать пользовательский ввод на целевых языках.
- Добавить логирование (опционально) игровых сессий для отладки.
Короткие сниппеты и подсказки
- Фильтрация списка слов при чтении:
with open("hangman_wordlist.txt", 'r', encoding='utf-8') as f:
wordlist = [w.strip() for w in f if w.strip()]- Сделать сравнения нечувствительными к регистру:
word = word.lower()
character = character.lower()- Хранить уже угаданные буквы, чтобы не штрафовать игрока дважды за ту же ошибку:
guessed = set()
if character in guessed:
print("You already tried that letter")
else:
guessed.add(character)Рекомендации по локализации для русскоязычной версии
- Используйте кодировку UTF-8 при чтении/записи файлов и при выводе в консоль.
- Если словарь содержит русские слова, убедитесь, что пользователи вводят буквы на русском — проверяйте кириллицу (метод isalpha() вернёт True для кириллицы).
- При переводе подсказок сохраните логику ответов (например, при запросе “да/нет” учитывайте возможные ответы в разных регистрах).
Краткая памятка (факты)
- Стандартное число попыток в примере: 7.
- Исходный файл слов содержит одно слово на строку.
- Рекомендуется фильтровать пустые строки и пробелы.
Итог
Вы получили рабочую пошаговую инструкцию по реализации классической игры «Виселица» на Python, исходный код ключевых функций и набор практических улучшений: локализация, валидация, тесты и идеи для перехода к GUI или веб-версии. Начните с базовой версии, затем добавляйте функциональность по списку улучшений и тестируйте каждый шаг.
Важно: перед релизом проверьте обработку нестандартного ввода и корректность чтения словаря. Удачи в разработке и расширении игры!