17 января 2024

🐍➰ Создаем игру «Виселица» на Python. Часть 2. Графический интерфейс на PySimpleGUI

Автор статей по блокчейну, криптовалюте, безопасности и общим темам
Во второй части реализуем логику игры «Виселица» и создадим графический интерфейс с помощью PySimpleGUI.
🐍➰ Создаем игру «Виселица» на Python. Часть 2. Графический интерфейс на PySimpleGUI
Данная статья является переводом. Ссылка на оригинал.

В этом руководстве вы займетесь созданием игры «Виселица» на Python в несколько этапов. Игра получит изящный графический интерфейс, базирующийся на библиотеке PySimpleGUI.

В этом уроке вы:

  • Создадите графический интерфейс для игры в виселицу с помощью PySimpleGUI
  • Реализуете логику для игры в виселицу
  • Свяжите логику игры с ее графическим интерфейсом
  • Обработаете результаты игры и настроите другие опции

Чтобы извлечь максимум пользы из этого урока, вы должны быть знакомы с общим программированием на Python, в том числе с процессом разработки проекта. Также у вас должен быть опыт работы с графическими пользовательскими интерфейсами, в особенности с теми, что базируются на PySimpleGUI. Вам не обязательно иметь какие-либо знания о программировании игр, но это будет плюсом.

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

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

Описание проекта

При создании GUI-версии виселицы вам понадобится GUI-фреймворк, способный работать с текстовыми играми, и при этом обеспечивающий возможность нарисовать повешенного человека. Python поддерживают несколько хороших GUI-движков. Хотя вы можете использовать любой из них для достижения желаемого эффекта, в этом уроке вы будете ориентироваться на PySimpleGUI.

PySimpleGUI – это программная оболочка для нескольких популярных GUI-фреймворков и библиотек, таких как Tkinter, wxPython и PyQt. В этом руководстве вы будете использовать оболочку Tkinter, но вы можете ознакомиться и с wxPython и QT на PyPI.

  • Подготовка к игре: Игра «Виселица» рассчитана на двух или более игроков, включая ведущего и одного или нескольких отгадывающих участников.
  • Выбор слова: Ведущий игры выбирает слово, которое пытаются угадать отгадывающие игроки.
  1. Выбранное слово традиционно изображается в виде серии подчеркиваний каждой буквы в слове.
  2. Ведущий игрок также рисует подмостки, на которых будет держаться иллюстрация виселицы.
  • Отгадывание: Игроки пытаются отгадать слово, выбирая буквы по одной.
  • Обратная связь: Ведущий игрок указывает, встречается ли в слове та или иная названная буква.
  1. Если буква встречается, то ведущий игрок заменяет каждое подчеркивание на букву, которая встречается в слове.
  2. Если буква не фигурирует, то ведущий игрок заносит ее в список отгаданных букв. Затем он рисует следующую часть повешенного. Чтобы нарисовать повешенного, начинают с головы, затем туловище, руки и ноги – всего шесть частей.
  • Условия победы: Ведущий игрок выигрывает, если рисунок повешенного завершен после шести неправильных предположений, в этом случае игра заканчивается. Отгадывающие игроки выигрывают, если угадывают слово.
  1. Если догадка верна – игра заканчивается, и отгадывающие игроки выигрывают.
  2. Если же предположение неверно, то игра продолжается.

Ниже изображена игра в процессе. В этой игре слово, которое нужно отгадать – это виселица:

Игра «Виселица»
Игра «Виселица»

В этом руководстве, чтобы написать игру «Виселица» на Python, вы должны принять несколько дополнительных решений:

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

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

🐍 Библиотека питониста
Больше полезных материалов вы найдете на нашем телеграм-канале «Библиотека питониста»
🐍🎓 Библиотека собеса по Python
Подтянуть свои знания по Python вы можете на нашем телеграм-канале «Библиотека собеса по Python»
🧩🐍 Библиотека задач по Python
Интересные задачи по Python для практики можно найти на нашем телеграм-канале «Библиотека задач по Python»

Обязательные условия

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

  • Создание приложений с графическим интерфейсом на базе PySimpleGUI
  • Работа с файлами и оператором with
  • Определение собственных классов и работа с объектно-ориентированным программированием
  • Использование циклов for, while и генераторов
  • Работа с условными операторами
  • Работа со строками, списками и множествами Python.

Статьи по теме

Шаг 1: Настройка проекта «Виселица»

Ваша игра «Виселица» будет реализована с помощью интерфейса PySimpleGUI, в котором пользователь сможет участвовать в процессе игры. Участник будет выбирать слово для отгадывания, а игра – обрабатывать вводимые пользователем данные и отображать все результаты с помощью графического интерфейса.

Вы можете скачать файлы и ресурсы для этого шага, использовав ссылку (в начале статьи) и перейдя в папку source_code_step_1/.

Для работы над игрой вы будете использовать отдельный файл hangman.py. В этом файле вы создадите класс Hangman, который будет содержать код для создания графического интерфейса и логики игры. Этот файл также будет включать в себя главный цикл игры, который будет управлять ее действиями.

Итак, создайте директорию hangman/, а затем – файл hangman.py с помощью вашего любимого редактора кода или IDE.

Вам также понадобится текстовый файл words.txt, в котором будет храниться список загаданных слов. Пример файла words.txt вы найдете в разделе «Выбор ключевого слова». Со вторым файлом у вас получится следующая структура каталогов для проекта виселицы:

        hangman/
├── hangman.py
└── words.txt

    

Благодаря этим файлам, у вас уже есть минимальная схема проекта, необходимая для создания игры в виселицу. Теперь необходимо сформировать виртуальную среду Python в hangman/ и установить библиотеку PySimpleGUI. Откройте окно командной строки в папке hangman/. Затем выполните следующие действия:

Windows:

        PS> python -m venv venv
PS> venv\Scripts\activate
(venv) PS> $ python -m pip install pysimplegui

    

Linux + macOS:

        $ python -m venv venv
$ source venv/bin/activate
(venv) $ python -m pip install pysimplegui

    

С помощью первых двух команд вы создаете и активируете виртуальную среду Python под названием venv в своем рабочем каталоге. После того как среда активирована, вы устанавливаете PySimpleGUI с помощью pip.

Шаг 2: Набросок графического интерфейса игры «Виселица»

При разработке пользовательского интерфейса для игры в виселицу вы будете помнить о следующих правилах:

  • Элементы управления игрой должны быть интуитивно понятны пользователю.
  • Элементы управления игрой должны отражать текущее состояние игры.
  • Для ввода и вывода информации в игре должны использоваться соответствующие компоненты GUI.

Чем более интуитивно понятны элементы управления, тем приятнее пользователю сразу же приступить к игре. Заставить элементы управления реагировать на изменения состояния игры – значит сократить время проверки правильности ввода и обеспечить игрока наглядной информацией. Кроме того, поскольку вы будете использовать графический интерфейс, имеет смысл задействовать графические компоненты везде, где только возможно.

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

Графический интерфейс вашей игры в виселицу должен выполнять несколько задач:

  1. Изображать повешенного человека.
  2. Демонстрировать заданное слово.
  3. Отображать ранее отгаданные буквы.
  4. Предоставлять игроку возможность отгадывать новые буквы.
  5. Разрешать игроку выйти из игры.

Вот первое понимание того, как будет выглядеть графический интерфейс вашей игры:

Графический интерфейс вашей игры «Виселица»
Графический интерфейс вашей игры «Виселица»

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

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

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

🐍➰ Создаем игру «Виселица» на Python. Часть 2. Графический интерфейс на PySimpleGUI

🐍 Подписывайтесь на еженедельную email-рассылку, посвященную последним открытиям и тенденциям в мире Python.

В ней:

  • Новые возможности в последних версиях Python
  • Работа с базами данных и SQL в Python
  • Веб-разработка на Django и Flask
  • Машинное обучение и анализ данных с помощью Python
  • Автоматизация и работа с API на Python
  • Тестирование и отладка кода на Python
  • Задачи для новичков с решениями

Шаг 3: Код GUI-приложения для виселицы

Чтобы приступить к реализации проекта PySimpleGUI, например, игры в виселицу, вам понадобится создать каркас приложения. Затем нужно заняться созданием графического интерфейса виселицы, следуя схеме из предыдущего шага. И наконец, вы напишете код для изображения повешенного.

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

Опять же, вы можете скачать исходный код для этого шага, использовав ранее полученный материал (папка source_code_step_3/).

Приложение PySimpleGUI, как правило, состоит из главного рабочего окна с определенным макетом или дизайном GUI и цикла событий. Чтобы создать игру «Виселица», откройте файл hangman.py в редакторе кода и добавьте в него следующий текст:

        import PySimpleGUI as sg

class Hangman:
    def __init__(self) -> None:
        self._window = sg.Window(
            title="Hangman",
            layout=[[]],
            finalize=True,
            margins=(100, 100),
        )

    def read_event(self):
        event = self._window.read()
        event_id = event[0] if event is not None else None
        return event_id

    def close(self):
        self._window.close()
    

В этом коде вы в первую очередь импортируете библиотеку PySimpleGUI под именем sg. Такой способ использования библиотеки широко распространен в ее официальной документации, в основном потому, что sg позволяет сэкономить на вводе текста. Кроме того, такой псевдоним может быть полезен, если вы захотите попробовать другой бэкенд, например, wxPython или QT.

Затем вы определяете класс Hangman. В инициализаторе класса, .__init__(), вы указываете окно приложения. Для этого вы вводите класс Window. В этом примере вы называете окно «Hangman». Затем вы используете список в качестве разметки окна. Обратите внимание, что это пустой список, вложенный в другой, который позволяет создать пустое окно.

Аргумент finalize позволяет указать, следует ли зафиксировать макет окна. Фиксация макета окна означает, что после создания окна вы не сможете изменять его оформление. В вашей игре «Виселица» окно должно сохранять свой внешний вид во время прохождения игры, поэтому вы устанавливаете значение finalize равным True.

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

Затем вы используете метод .read_event(). Он основан на базе Window.read() и позволяет считывать все пользовательские действия в графическом интерфейсе приложения. Помните, что приложения с графическим интерфейсом работают на базе определенных действий, следовательно, они перехватывают, обрабатывают и реагируют на такие изменения, как клики мышью, нажатия клавиш и другие.

И наконец, у вас есть метод .close(). С его помощью вы можете закрыть главное окно приложения и завершить его работу.

Теперь, когда у вас есть главное окно приложения, необходимо задать цикл работы приложения. Этот цикл позволяет запускать приложение и обрабатывать действия пользователя в последовательности. Вот один из вариантов составления минимального цикла для игры в виселицу:

        # ...

if __name__ == "__main__":
    game = Hangman()
    # Event loop
    while True:
        event_id = game.read_event()
        if event_id in {sg.WIN_CLOSED}:
            break
    game.close()
    

Поскольку ваш файл hangman.py включает в себя исполняемый код, вы используете функцию name-main, чтобы завершить цикл. Перед началом цикла вы используете элемент класса Hangman под названием game.

Чтобы задать цикл действий, вы используете бесконечный цикл while. Первая строка кода внутри цикла вызывает .read_event() на объекте game, чтобы перехватить любое пользовательское действие в начале цикла.

Метод .read_event() возвращает идентификатор действия или None. Вы используете этот идентификатор в заключительной части цикла, где условный оператор проверяет, входит ли текущее значение в набор возможных действий, которые позволят вам выйти из цикла и завершить работу приложения. На данный момент этот список содержит только идентификатор sg.WIN_CLOSED. Однако в будущем он будет включать в себя и сигнал от кнопки Quit.

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

🐍➰ Создаем игру «Виселица» на Python. Часть 2. Графический интерфейс на PySimpleGUI

Отлично! У вашего окна появилась соответствующая надпись, и она позволяет вам нажать кнопку «Закрыть» в панели заголовка, чтобы завершить работу приложения. Теперь пришло время для создания графического интерфейса виселицы.

Шаг 4: Создание графического интерфейса виселицы

PySimpleGUI позволяет создавать графические интерфейсы в декларативном виде как данные, а не программно как код. В этом смысле библиотека похожа на другие инструменты для создания графических интерфейсов, такие как Qt Designer, который осуществляет генерацию графических интерфейсов в виде данных с использованием XML. Это отличная возможность, позволяющая отделить дизайн GUI от функциональности приложения.

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

Чтобы загрузить исходный код для этого шага перейдите в папку source_code_step_4/:

Создание графического интерфейса виселицы

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

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

🐍➰ Создаем игру «Виселица» на Python. Часть 2. Графический интерфейс на PySimpleGUI

Красными линиями выделены основные элементы пользовательского интерфейса, разбитые на ряды:

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

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

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

Макет PySimpleGUI – это обычный список Python. Поскольку глобальный макет GUI состоит из трех строк, вам нужно создать список с тремя вложенными блоками. Обновите класс Hangman, как показано в приведенном ниже коде:

        # ...

class Hangman:
    def __init__(self) -> None:
        layout = [
            [
                self._build_canvas_frame(),
                self._build_letters_frame(),
            ],
            [
                self._build_guessed_word_frame(),
            ],
            [
                self._build_action_buttons_frame(),
            ],
        ]
        self._window = sg.Window(
            title="Hangman",
            layout=layout,
            finalize=True,
        )

    # ...
    

В этом фрагменте кода вы задаете структуру макета как список списков в Python. Все вложенные списки содержат вызываемые методы. Вы реализуете все эти методы в ближайшее время.

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

Второй вложенный список содержит вызываемый метод для создания ряда угаданных слов. И наконец, третий вложенный список содержит метод для создания кнопок действий «Новая игра», «Сброс» и «Выход». Последнее обновление в этом коде – удаление аргумента margins из характеристики объекта ._window.

Чтобы визуально отделить каждый элемент в строке, вы будете использовать класс Frame. Таким образом, у вас будет четыре основных рамки:

  1. Рамка области изображения повешенного человека
  2. Рамка буквенных кнопок
  3. Рамка загаданного слова
  4. Рамки кнопок «Новая игра», «Сброс» и «Выход».

Для создания области изображения повешенного человека вы используете класс Graph. Ниже приведен необходимый код для дополнительного метода ._build_canvas_frame():

        # ...

class Hangman:
    # ...

    def _build_canvas_frame(self):
        return sg.Frame(
            "Hangman",
            [
                [
                    sg.Graph(
                        key="-CANVAS-",
                        canvas_size=(200, 400),
                        graph_bottom_left=(0, 0),
                        graph_top_right=(200, 400),
                    )
                ]
            ],
            font="Any 20",
        )

    # ...
    

В данном методе вначале необходимо создать объект Frame с заголовком «Hangman». Фрейм содержит список с вложенным в него содержимым. Этот список представляет собой макет рамки.

Объект Graph располагает ключом -CANVAS-. Вы будете использовать этот ключ для доступа к изображению вашего объекта Graph. Размер полотна составляет 200 пикселей в ширину и 400 пикселей в высоту, левый нижний угол равен (0, 0), а правый – (200, 400). Эти координаты будут необходимы при написании кода для изображения повешенного человека.

💡Примечание
Обычно в PySimpleGUI в качестве ключа объекта используется строка с описанием. Однако ключи могут быть любого хешируемого типа, например, int, tuple или str. В этом примере вы будете использовать строки в верхнем регистре с первым и последним дефисом, что широко распространено в большинстве демонстрационных примеров PySimpleGUI.

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

Приведем пример кода для создания рамки с буквами:

        from string import ascii_uppercase
# ...

class Hangman:
    # ...

    def _build_letters_frame(self):
        letter_groups = [
            ascii_uppercase[i : i + 4]
            for i in range(0, len(ascii_uppercase), 4)
        ]
        letter_buttons = [
            [
                sg.Button(
                    button_text=f" {letter} ",
                    font="Courier 20",
                    border_width=0,
                    button_color=(None, sg.theme_background_color()),
                    key=f"-letter-{letter}-",
                    enable_events=True,
                )
                for letter in letter_group
            ]
            for letter_group in letter_groups
        ]
        return sg.Column(
            [
                [
                    sg.Frame(
                        "Letters",
                        letter_buttons,
                        font="Any 20",
                    ),
                    sg.Sizer(),
                ]
            ]
        )

    # ...
    

В этом коде присутствует много интересного. Вот его краткое описание:

  • В строках с 8 по 11 используется список для получения набора букв, который поможет вам заполнить семь буквенных строк. Для этого используется объект ascii_uppercase из модуля string.
  • Строки с 12 по 25 создают новый список с помощью другого метода, который выполняет итерацию групп букв, а затем каждой буквы в группах. Создается вложенный список объектов Button. Каждая кнопка будет обозначать букву. Вы также настраиваете кнопки, изменяя некоторые их свойства, включая шрифт, границы, цвет и клавишу.
  • В строках 26-37 создается и используется объект Column. Макет этого объекта содержит один вложенный список, в котором находится рамка со всеми кнопками-буквами. Обратите внимание, что этот фрейм будет иметь заголовок «Буквы».

Используя дополнительный метод ._build_letters_frame(), вы можете приступить к реализации ._build_guessed_word_frame():

        # ...

class Hangman:
    # ...

    def _build_guessed_word_frame(self):
        return sg.Frame(
            "",
            [
                [
                    sg.Text(
                        key="-DISPLAY-WORD-",
                        font="Courier 20",
                    )
                ]
            ],
            element_justification="center",
        )

    # ...
    

Эта строка содержит только один элемент – объект Text, в котором будет храниться загаданное слово, которое вы выведете на экран для оповещения игрока. Установите шрифт Courier, чтобы каждый символ занимал равное пространство по горизонтали.

Последний ряд макета игры будет содержать три кнопки для управления другим игровым процессом:

        # ...

class Hangman:
    # ...

    def _build_action_buttons_frame(self):
        return sg.Frame(
            "",
            [
                [
                    sg.Sizer(h_pixels=90),
                    sg.Button(
                        button_text="New",
                        key="-NEW-",
                        font="Any 20",
                    ),
                    sg.Sizer(h_pixels=60),
                    sg.Button(
                        button_text="Restart",
                        key="-RESTART-",
                        font="Any 20",
                    ),
                    sg.Sizer(h_pixels=60),
                    sg.Button(
                        button_text="Quit",
                        key="-QUIT-",
                        font="Any 20",
                    ),
                    sg.Sizer(h_pixels=90),
                ]
            ],
            font="Any 20",
        )

    # ...
    

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

И наконец, обратите внимание на атрибут key каждой кнопки. Любые элементы GUI, с которыми вы хотите взаимодействовать, должны обладать ключом. Используя этот ключ, вы можете ссылаться на элемент и знать, какой объект инициировал то или иное действие. Как использовать ключи, вы узнаете в следующих разделах.

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

Изображение повешенного человека

Для того чтобы нарисовать повешенного человека, вам необходимо получить ссылку на поле для рисования. В предыдущем разделе вы добавили объект Graph в макет вашего приложения. Этот объект и будет служить областью рисования. Чтобы идентифицировать объект, вы использовали ключ "-CANVAS-". Этот ключ позволит вам создать ссылку на объект, чтобы вы могли нарисовать повешенного человека.

Добавьте следующую строку в инициализатор «Виселицы»:

        # ...

class Hangman:
    def __init__(self) -> None:
        # ...
        self._canvas = self._window["-CANVAS-"]

    # ...
    

Эта строка кода содержит атрибут ._canvas, который ссылается на область рисования. Теперь можно приступать к работе.

Прежде чем приступать к рисованию, необходимо понять, что для изображения линий и фигур в объекте Graph используются 2D-координаты при определении конкретных точек на холсте. После этого вы можете нарисовать линии и фигуры, используя их в качестве ориентиров. Для определения пары координат используются кортежи с двумя значениями.

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

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

        # ...

class Hangman:
    # ...

    def _draw_scaffold(self):
        lines = [
            ((40, 55), (180, 55), 10),
            ((165, 60), (165, 365), 10),
            ((160, 360), (100, 360), 10),
            ((100, 365), (100, 330), 10),
            ((100, 330), (100, 310), 1),
        ]
        for *points, width in lines:
            self._canvas.DrawLine(*points, color="black", width=width)

    # ...
    

Чтобы нарисовать леса, вам понадобится несколько линий, а для определения линии – две точки. Вы можете указать каждую точку в виде кортежа с двумя значениями. Список lines включает в себя кортежи, в которых указаны точки для каждой линии. Они также содержат конечное значение, которое представляет собой ширину линии.

В цикле for вы перебираете линии, извлекая точки и значения ширины в соответствующие переменные цикла. Затем вы используете метод .DrawLine() объекта Graph, чтобы нарисовать линии. Вы увидите этот метод в действии немного позже.

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

  • Голова
  • Туловище
  • Левая и правая руки
  • Левая и правая ноги

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

        # ...

class Hangman:
    # ...

    def _draw_hanged_man(self):
        head = (100, 290)
        torso = [((100, 270), (100, 170))]
        left_arm = [
            ((100, 250), (80, 250)),
            ((80, 250), (60, 210)),
            ((60, 210), (60, 190)),
        ]
        right_arm = [
            ((100, 250), (120, 250)),
            ((120, 250), (140, 210)),
            ((140, 210), (140, 190)),
        ]
        left_leg = [
            ((100, 170), (80, 170)),
            ((80, 170), (70, 140)),
            ((70, 140), (70, 80)),
            ((70, 80), (60, 80)),
        ]
        right_leg = [
            ((100, 170), (120, 170)),
            ((120, 170), (130, 140)),
            ((130, 140), (130, 80)),
            ((130, 80), (140, 80)),
        ]
        body = [
            torso,
            left_arm,
            right_arm,
            left_leg,
            right_leg,
        ]
        if self._wrong_guesses == 1:
            self._canvas.DrawCircle(
                head,
                20,
                line_color="red",
                line_width=2,
            )
        elif self._wrong_guesses > 1:
            for part in body[self._wrong_guesses - 2]:
                self._canvas.DrawLine(*part, color="red", width=2)

    # ...
    

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

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

Для рисования рук вам понадобятся три линии. Они будут изображать плечо, руку и предплечье соответственно. Для ног – четыре линии. Они будут обозначать бедро, колено, икру и стопу соответственно. Туловище, руки и ноги – все эти линии образуют тело. Таким образом, вы объединяете их в один список.

Следующий шаг – нарисовать голову и тело. Чтобы нарисовать голову, вы используете метод .DrawCircle(), который принимает в качестве аргумента центральную точку. Вы также устанавливаете радиус окружности в двадцать пикселей, цвет линии – красный, а ширину линии – два пикселя.

Теперь вы рисуете тело с помощью метода .DrawLine(). И снова вы устанавливаете цвет линии – красный, а ее ширину в два пикселя.

Чтобы увидеть весь этот код в действии, добавьте следующий текст в инициализатор «Виселицы»:

        # ...
MAX_WRONG_GUESSES = 6

class Hangman:
    def __init__(self) -> None:
        # ...
        self._canvas = self._window["-CANVAS-"]
        # Temporary code
        self._draw_scaffold()
        for index in range(MAX_WRONG_GUESSES):
            self._wrong_guesses = index + 1
            self._draw_hanged_man()

    # ...
    

В этом фрагменте кода вы определяете константу MAX_WRONG_GUESSES. Что это за постоянная? Рисунок повешенного человека состоит из шести частей. Вы будете рисовать каждую часть постепенно, по мере того как игрок будет ошибаться в выборе букв. Таким образом, MAX_WRONG_GUESSES должно быть равно 6, что является максимальным количеством неправильных догадок, при котором игрок выбывает из игры.

В этом предварительном коде в конце фрагмента вы сперва вызываете ._draw_scaffold(), прорисовывая строительные леса, а затем запускаете цикл по интервалу, который вы определяете с помощью MAX_WRONG_GUESSES.

Внутри цикла вы обновляете значение ._wrong_guesses. Вы узнаете об этом атрибуте позже. Пока что вы используете его в качестве промежуточного параметра. И наконец, вы используете метод ._draw_hanged_man(). Если вы запустите приложение сейчас, то получите окно, аналогичное следующему:

Игра «Виселица»
Игра «Виселица»

Великолепно! Ваша игра «Виселица» приобретает законченную форму. Вы создали подходящий графический интерфейс для игры, который отлично смотрится! Однако графический интерфейс пока не реагирует на пользовательские действия. Вам предстоит исправить это, спроектировав логику игры и подключив ее к графическому интерфейсу.

Шаг 5: Разработка логики игры и подключение ее к графическому интерфейсу

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

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

  • Выбор подходящего слова
  • Отслеживание загаданного слова или букв
  • Запуск новой игры
  • Обработка ходов игрока
  • Определение момента окончания игры.

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

Чтобы загрузить исходный код для этого шага перейдите в папку source_code_step_5/.

Выбор слова для отгадывания

Первый шаг в игре в виселицу – выбор слова-задания. Когда игрок выбирает слово для игры в виселицу, он использует одно слово из своего словарного запаса. Чтобы компьютер подобрал слово, ему необходимо иметь собственный словарь. Конечно, его словарный запас не должен быть таким же большим, как у человека.

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

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

        from random import choice
# ...

class Hangman:
    # ...

    def _select_word(self):
        with open("words.txt", mode="r", encoding="utf-8") as words:
            word_list = words.readlines()
        return choice(word_list).strip().upper()

    # ...
    

В этом фрагменте кода вы используете метод ._select_word() для выбора слова для отгадывания из файла words.txt. Вы используете оператор with для открытия файла и метод .readlines() для создания списка слов. Затем, с помощью метода choice(), выбираете случайное слово из списка.

Отслеживание загаданного слова

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

Чтобы сымитировать вышеописанный процесс в вашей игре в виселицу, вы будете использовать следующий вспомогательный метод:

        # ...

class Hangman:
    # ...

    def _build_guessed_word(self):
        current_letters = []
        for letter in self._target_word:
            if letter in self._guessed_letters:
                current_letters.append(letter)
            else:
                current_letters.append("_")
        return " ".join(current_letters)

    # ...
    

Эта функция использует цикл for для заполнения списка current_letters. Цикл просматривает каждую букву в атрибуте ._target_word и определяет, содержится ли эта буква в ._guessed_letters. Если это так, то программа добавляет букву в current_letters. Если нет, то она добавляет знак подчеркивания _ к current_letters. После этого вы используете метод .join() для создания отображаемого слова, которое будет включать правильные буквы в соответствующих местах.

Обратите внимание, что вы еще не определили атрибуты ._target_word и ._guessed_letters. Вы сделаете это в следующем разделе.

Запуск или перезапуск игры

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

  1. Заданное слово, ._target_word
  2. Угаданные буквы, ._guessed_letters
  3. Количество неправильных догадок, ._wrong_guesses
  4. Отображение загаданного слова, ._guessed_word

Для того чтобы определить, как вы начнете новую игру, вам необходимо инициализировать все эти атрибуты. Для этого используется метод ._new_game():

        # ...

class Hangman:
    # ...

    def _new_game(self):
        self._target_word = self._select_word()
        self._restart_game()

    # ...
    

Внутри ._new_game() вы определяете атрибут ._target_word, который будет содержать выбранное слово для начала новой игры. Чтобы определить, какое слово использовать, вы обращаетесь к методу ._select_word().

Затем вы используете метод ._restart_game(). В этом методе вы инициализируете остальные атрибуты, определяющие состояние игры. Обратите внимание, что наличие двух независимых методов облегчит поддержку кнопок «Новая игра» и «Перезапуск» соответственно. Вы сделаете это в следующем разделе.

Теперь напишите код для метода ._restart_game():

        # ...

class Hangman:
    # ...

    def _restart_game(self):
        self._guessed_letters = set()
        self._wrong_guesses = 0
        self._guessed_word = self._build_guessed_word()
        # Restart GUI
        self._canvas.erase()
        self._draw_scaffold()
        for letter in ascii_uppercase:
            self._window[f"-letter-{letter}-"].update(disabled=False)
        self._window["-DISPLAY-WORD-"].update(self._guessed_word)

    # ...
    

Для отслеживания отгаданных букв вы будете использовать множество Python. Использование множества позволяет оперативно проверять, отгадал ли игрок заданную букву, используя тесты принадлежности с помощью оператора in.

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

Последние строки этого метода напрямую связаны с графическим интерфейсом игры и требуют более подробного объяснения.

Каждый раз, когда вы перезапускаете игру, вам необходимо сбросить рисунок повешенного человека. Для этого вы в первую очередь обращаетесь к методу .erase() объекта Graph, который используется в качестве холста. Затем вы перерисовываете строительные леса. После этих изменений область рисования готова к запуску новой или перезапуску игры.

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

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

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

Обработка вводимых игроком данных

В рамках реализации игры «Виселица», ход совершается, когда угадывающий игрок нажимает на кнопку с буквой. Клик – это действие, поэтому вы можете перехватить его и обработать, используя возможности PySimpleGUI. Для этого вы используете два метода, .process_event() и ._play().

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

Ниже приведен код с использованием метода .process_event():

        # ...

class Hangman:
    # ...

    def read_event(self):
        # ...

    def process_event(self, event):
        if event[:8] == "-letter-":
            self._play(letter=event[8])
        elif event == "-RESTART-":
            self._restart_game()
        elif event == "-NEW-":
            self._new_game()

    # ...
    

В .process_event() аргумент event содержит только идентификатор действия, который вы задали через аргумент key, когда назначали кнопки в макете. Условный оператор проверяет, является ли текущее действие щелчком по кнопке с буквой.

Изначально вы задали для клавиши letters значение f"-letter-{letter}-". В условном операторе проверяется, совпадают ли первые восемь символов в идентификаторе текущего действия со строкой "-letter-". Таким образом можно определить, что текущее действие – это нажатие на кнопку с буквой. Если это так, тогда вы обращаетесь к методу ._play() с текущей буквой в качестве аргумента.

Условия elif обрабатывают действия "-RESTART-" и "-NEW-" соответственно. Действие "-RESTART-" осуществляется, когда игрок нажимает кнопку «Перезапуск», а действие "-NEW-" – когда игрок нажимает кнопку «Новая игра». В любом случае вы вызываете соответствующий метод.

Теперь необходимо сформулировать метод ._play():

        # ...

class Hangman:
    # ...

    def _restart_game(self):
        # ...

    def _play(self, letter):
        if letter not in self._target_word:
            self._wrong_guesses += 1
        self._guessed_letters.add(letter)
        self._guessed_word = self._build_guessed_word()
        # Update GUI
        self._window[f"-letter-{letter}-"].update(disabled=True)
        self._window["-DISPLAY-WORD-"].update(self._guessed_word)
        self._draw_hanged_man()

    # ...
    

В методе ._play() прежде всего проверяется, нет ли угаданной буквы в заданном слове. В этом случае счетчик неправильных догадок увеличивается на единицу. Если текущая буква есть в загаданном слове, то она добавляется в список угаданных букв, что позволяет вести их учет. Затем вы обновляете загаданное слово, вызывая ._build_guessed_word().

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

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

Определение завершения игры

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

Обычно «Виселица» заканчивается, когда происходит одно из двух событий:

  • Игрок допустил шесть ошибочных догадок, что свидетельствует о его проигрыше.
  • Игрок правильно отгадал слово, и, соответственно, победил.

У вас имеются два условия для проверки, поэтому вы можете включить их в отдельный метод. Вы назовете метод .is_over(), и это будет предикатный метод, возвращающий True или False.

Ниже представлена его реализация:

        # ...

class Hangman:
    # ...

    def process_event(self, event):
        # ...

    def is_over(self):
        return any(
            [
                self._wrong_guesses == MAX_WRONG_GUESSES,
                set(self._target_word) <= self._guessed_letters,
            ]
        )

    # ...
    

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

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

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

Затем с помощью оператора <= вы сравниваете этот массив с множеством, содержащим отгаданные буквы. Это выражение проверяет, является ли каждый элемент левого списка членом правого множества. Если это так – значит, игрок отгадал все буквы, выполнив второе условие.

Встроенная функция any() возвращает True, если хотя бы одно из перечисленных условий истинно. В противном случае она возвращает False.

Результат выполнения функции .is_over() зависит от хода игрока. Поэтому имеет смысл использовать этот метод для управления циклом событий игры.

Обновление цикла событий и запуск игры

До этого момента вы проделали большую работу по написанию кода. Вы реализовали логику виселицы и подключили ее к графическому интерфейсу на основе PySimpleGUI. Однако вам необходимо реализовать весь этот код в реальной игре. Вы сделаете это в общем игровом цикле.

Обновите главный цикл, как показано в приведенном ниже коде:

        # ...

if __name__ == "__main__":
    game = Hangman()
    # Event loop
    while not game.is_over():
        event_id = game.read_event()
        if event_id in {sg.WIN_CLOSED}:
            break
        game.process_event(event_id)
    game.close()
    

В новой версии цикла событий вашей игры вы используете .is_over() для управления им. Теперь цикл будет выполняться до тех пор, пока не будет соблюдено одно из условий завершения игры. Внутри цикла вы включаете функцию .process_event() с идентификатором текущего действия в качестве аргумента.

Вы можете заметить, что теперь кнопки с буквами, изображение повешенного человека и загаданное слово наконец-то заработали. Вы даже можете сыграть свой первый матч. Вы также увидите, что кнопки «Новая игра» и «Перезапуск» функционируют.

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

Шаг 6: Обработка результатов игры

На этом шаге у вас уже имеется функциональная игра «Виселица». В ней можно отгадывать заданное слово, нажимая на кнопки с буквами. Кнопки «Новая игра» и «Перезапуск» также работают. Однако игра автоматически закрывается, когда вы выигрываете или проигрываете текущий матч. Это не очень приятно, не так ли?

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

Опять же, вы можете скачать исходный код для этого шага и перейти в папку source_code_step_6/.

Определение победителя и повторная игра

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

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

        # ...

class Hangman:
    # ...

    def is_over(self):
        # ...

    def check_winner(self):
        if self._wrong_guesses < MAX_WRONG_GUESSES:
            answer = sg.PopupYesNo(
                "You've won! Congratulations!\n"
                "Another round?",
                title="Winner!",
            )
        else:
            answer = sg.PopupYesNo(
                f"You've lost! The word was '{self._target_word}'.\n"
                "Another round?",
                title="Sorry!",
            )
        self.quit = answer == "No"
        if not self.quit:
            self._new_game()

    # ...
    

В функции .check_winner() вы проверяете, не превышает ли количество неверных предположений максимальное число допустимого значения – 6. Помните, что это число соответствует количеству элементов на изображении повешенного человека. Если условие истинно, то игрок выиграл, и вы выводите поздравительное сообщение во всплывающем окне.

Если условие ложно, то вы отображаете всплывающее окно, сообщающее игроку, что он проиграл. В нем также содержится информация о загаданном слове.

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

Если значение .quit равно False, то вы обращаетесь к ._new_game(), чтобы сбросить загаданное слово и начать новую игру в виселицу.

Чтобы этот код заработал, вам необходимо добавить атрибут .quit в инициализатор класса Hangman:

        # ...

class Hangman:
    def __init__(self):
        # ...
        self._new_game()
        self.quit = False

    # ...
    

Эта новая строка кода добавляет атрибут .quit в Hangman. По умолчанию атрибут имеет значение False. Теперь, когда все эти изменения внесены, можно обновить цикл игры. Чтобы управлять множеством раундов, вы заключите цикл событий во внешний цикл, связанный с атрибутом .quit:

        # ...

if __name__ == "__main__":
    game = Hangman()
    # Rounds
    while not game.quit:
        # Event loop
        while not game.is_over():
            event_id = game.read_event()
            if event_id in {sg.WIN_CLOSED, "-QUIT-"}:
                game.quit = True
                break
            game.process_event(event_id)

        if not game.quit:
            game.check_winner()

    game.close()
    

В этом обновленном коде вы заключаете цикл событий во внешний цикл, который позаботится об обработке нескольких раундов игры в виселицу. Этот внешний цикл использует атрибут .quit в процессе выполнения условий. Цикл будет повторяться до тех пор, пока игрок не закроет окно игры или не нажмет кнопку «Выход». В этот момент атрибут .quit станет True, а условие цикла – false.

Две предпоследние строки включают в себя условный оператор, который проверяет, вышел ли игрок из игры. Если это так, тогда вы обращаетесь к методу .check_winner().

Когда вы угадываете заданное слово, игра выводит сообщение о вашей победе и приглашает сыграть еще один матч. Если вы нажмете кнопку «Да», то игра выберет другое подходящее слово, и вы сможете начать новый раунд. Если вы нажмете кнопку «Нет», то игра завершится. Попробуйте!

Ведение счета и результаты

Отлично, теперь вы знаете, кто победил в одиночной игре! Но что, если ваш пользователь захочет помериться силами с компьютером в игре «Лучший из трех»? Ведение счета игрока на протяжении нескольких раундов – еще одна интересная функция в игре «Виселица». Вы можете отслеживать проведенные и выигранные партии. Итак, вам потребуется добавить два новых атрибута:

        # ...

class Hangman:
    def __init__(self):
        # ...
        self.quit = False
        self._played_games = 0
        self._won_games = 0

    # ...
    

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

Для этого вы можете отредактировать метод .check_winner(), как показано в приведенном ниже фрагменте кода:

        # ...

class Hangman:
    # ...

    def check_winner(self):
        self._played_games += 1
        if self._wrong_guesses < MAX_WRONG_GUESSES:
            self._won_games += 1
            answer = sg.PopupYesNo(
                "You've won! Congratulations!\n"
                f"That's {self._won_games} out of {self._played_games}!\n"
                "Another round?",
                title="Winner!",
            )
        else:
            answer = sg.PopupYesNo(
                f"You've lost! The word was '{self._target_word}'.\n"
                f"That's {self._won_games} out of {self._played_games}!\n"
                "Another round?",
                title="Sorry!",
            )
        self.quit = answer == "No"
        if not self.quit:
            self._new_game()

    # ...
    

В первой строке .check_winner() вы увеличиваете количество сыгранных игр с помощью добавочного присваивания. В условии if вы увеличиваете количество выигрышей. Эти два счетчика позволяют отслеживать необходимую информацию, которую затем добавляют в сообщение, отображаемое в каждом из всплывающих окон.

Ваша игра «Виселица» готова к чемпионату! Она позволяет проводить несколько раундов, а также ведет подсчет очков и информирует о ваших результатах. Попробуйте, а затем пригласите друзей!

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

Заключение

Создание игры «Виселица» с помощью Python и PySimpleGUI – это отличный способ развития навыков программирования, изучения новых техник и знакомства с миром компьютерных игр на базе GUI. Написав игру на Python, вы решили несколько задач по кодированию и дизайну, включая создание подходящего графического интерфейса, получение и обработку пользовательских действий, а также обновление интерфейса игры в зависимости от ее состояния.

В этом руководстве вы узнали, как:

  • Использовать PySimpleGUI при создании графического интерфейса пользователя для игры в виселицу
  • Реализовать логику и правила игры в виселицу на Python
  • Связывать логику игры и компоненты графического интерфейса пользователя
  • Оценивать результаты игры и предлагать пользователям дополнительные опции

Теперь у вас есть все необходимые инструменты и навыки, благодаря которым вы можете дополнять и совершенствовать свою игру «Виселица». Вы также можете заняться созданием других подобных игр.

Следующие шаги

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

Предлагаем вам несколько идей:

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

Чем вы займетесь дальше? Поделитесь своими идеями в комментариях!

Статьи по теме

Источники

Комментарии

ВАКАНСИИ

Добавить вакансию
Разработчик C++
Москва, по итогам собеседования

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ