Код #Статьи

25 августа, 2025

Примеры работы с ООП: 8-я часть гайда по объектно-ориентированному программированию / Skillbox Media

Заключительная часть серии статей про ООП, в которой мы создадим небольшой проект.

Бесплатный курс по Python ➞ Мини-курс для новичков и для опытных кодеров. 4 крутых проекта в портфолио, живое общение со спикером. Кликните и узнайте, чему можно научиться на курсе.

Узнать больше

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

  • Что такое классы и объекты.
  • Особенности работы с объектами.
  • Модификаторы доступа, инкапсуляция.
  • Полиморфизм и перегрузка методов.
  • Полиморфизм.
  • Наследование и ещё немного полиморфизма.
  • Абстрактные классы и интерфейсы.
  • Практикум.

Какой будет игра

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

Устроена игра будет так:

  • При запуске вызывается метод InitGame (), в котором будут созданы игровые объекты, предметы и прочее.
  • После будет вызван метод Update (), который обновляет состояние игры.

Внутри метода Update () должен находиться цикл со следующими действиями:

  • Отрисовка локации или инвентаря.
  • Получение нажатой игроком клавиши.
  • Передача клавиши в контроллер.
  • Контроллер, в зависимости от нажатой клавиши, будет вызывать методы игровых объектов: например, Move () или Use ().

Для управления игрой мы используем три статических класса-контроллера:

  • LocationController — перехватывает действия игрока на локации.
  • InventoryController — перехватывает действия игрока в инвентаре.
  • GraphicsController — управляет выводом.

Игровые данные (размеры локации, список объектов) находятся в статическом классе Game. Объекты будут реализованы с помощью классов GameObject (базовый), Player и NPC. За расположение и перемещение по локации пусть отвечает класс Position.

Предметы реализуются с помощью классов Item (базовый), Potion и Meal. Если предмет может быть использован, то в нём реализуется интерфейс IUsable.

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

Создание игровых объектов

Начнём с класса GameObjects — он будет родительским для Player и NPC:

Обратите внимание на метод Die () — он выполняется, когда у объекта кончается здоровье. Метод удаляет объект из коллекции Game.Objects, что освобождает память. Схожую функцию выполняют деструкторы — они вызываются перед тем, как объект будет удалён из памяти.

Класс NPC позволит в дальнейшем реализовать логику для игрового ИИ. Player же содержит методы для управления персонажем игрока. Например, чуть позже мы реализуем в нём использование предметов из инвентаря.

Как уже говорилось выше, созданные объекты будут храниться в коллекции статического класса Game. Вот как это выглядит:

Вы могли заметить тут тип данных GameMode — это класс перечислений, который упрощает создание списков в коде:

Одна из альтернатив классам-перечислениям — числа. То есть мы могли бы просто написать так:

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

Графика

Теперь, чтобы заставить объекты и локацию отображаться, напишем класс GraphicsController:

Объекты рисуются с помощью символов, которые меняются в зависимости от того, в какую сторону направлен объект.

Теперь можно обновить класс Program, чтобы создать первые объекты и отобразить их в консоли:

Вот что должно быть выведено:

Управление

Чтобы заставить объект игрока двигаться, реализуем управление:

Этот класс проверяет нажатую игроком клавишу и передаёт команды дальше. Например, классу Position, который отвечает за перемещение объектов по локации.

Можно проверить, как работает перемещение:

А вместе с перемещением и боевую систему:

Инвентарь

Инвентарь начинается с класса Item:

Классы Potion и Meal практически идентичные, за исключением выводимых надписей. Поэтому здесь будет показан код только одного из классов:

Можно заметить, что класс наследует интерфейс IUsable:

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

Также в классе Program добавьте в switch с режимами следующий вариант:

Управление будет производиться с помощью InventoryController:

Теперь самое интересное — объект Player:

Тут вы можете увидеть два новых ключевых слова:

  • is — проверяет, реализован ли в данном объекте указанный интерфейс;
  • as — получает реализацию интерфейса.

Вот что получилось в итоге: