Menu
Coddy logo textTech

Система игровых персонажей

Часть раздела Объектно-ориентированное программирование путешествия по GO на Coddy — урок 107 из 107.

challenge icon

Задание

Легко

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

Вы организуете свой код в пяти файлах:

  • character.go: Определите базовую структуру Character с общими полями: Name (string), Health (int) и MaxHealth (int). Включите конструктор NewCharacter и методы:
    • IsAlive() bool — возвращает true, если здоровье больше 0
    • Status() string — возвращает строку в формате: [Name]: [Health]/[MaxHealth] HP
  • interfaces.go: Определите интерфейсы боя, обеспечивающие полиморфизм:
    • Интерфейс Attacker с методом Attack() int — возвращает нанесенный урон
    • Интерфейс Defender с методом TakeDamage(damage int) int — применяет снижение урона и возвращает фактически полученный урон
    • Интерфейс Ability с методом Use() string — возвращает описание эффекта способности
  • characters.go: Создайте три типа персонажей, которые встраивают Character и реализуют интерфейсы Attacker и Defender:

    Warrior — имеет поля Strength (int) и Armor (int). Метод Attack возвращает Strength в качестве урона. TakeDamage уменьшает входящий урон на значение Armor (минимум 1 единица полученного урона).

    Mage — имеет поля Intelligence (int) и MagicResist (int). Метод Attack возвращает Intelligence * 2 в качестве урона. TakeDamage уменьшает входящий урон на MagicResist / 2 (минимум 1 единица полученного урона).

    Archer — имеет поля Agility (int) и Evasion (int). Метод Attack возвращает Agility + 5 в качестве урона. TakeDamage: если Evasion > 10, уменьшает урон на 25% (целочисленное деление), в противном случае наносится полный урон (минимум 1 единица полученного урона).

    Включите конструкторы для каждого типа: NewWarrior, NewMage, NewArcher, которые принимают имя, здоровье и значения специфических характеристик.

  • abilities.go: Реализуйте паттерн «Стратегия» со сменными способностями:

    Структура FireSpell с полем Power (int). Её метод Use() возвращает: Casts fireball for [Power] damage

    Структура IceSpell с полем Power (int). Её метод Use() возвращает: Casts ice shard for [Power] damage

    Структура PowerStrike с полем Multiplier (int). Её метод Use() возвращает: Performs power strike at [Multiplier]x damage

    Добавьте поле ability (типа Ability) в структуру Mage, а также методы SetAbility(a Ability) и UseAbility() string. UseAbility возвращает No ability set, если способность не установлена (nil).

  • main.go: Создайте персонажей и продемонстрируйте механику боя.

    Считайте тип персонажа (warrior, mage или archer), затем считайте имя персонажа, здоровье и специфические для типа характеристики. Создайте соответствующего персонажа.

    Затем считайте количество действий. Каждое действие представляет собой одно из следующих:

    • status — вывести статус персонажа
    • attack — вывести [Name] attacks for [damage] damage
    • defend [amount] — применить урон и вывести [Name] takes [actual] damage
    • setability [type] [power] — только для магов, установить способность (тип: fire, ice или strike)
    • useability — только для магов, вывести результат метода Use() способности

Будут предоставлены следующие входные данные:

  • Тип персонажа, имя, здоровье и специфические характеристики
  • Количество действий, затем каждое действие на отдельной строке

Например, для входных данных:

warrior
Thorin
100
15
8
5
status
attack
defend 20
status
defend 100

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

Thorin: 100/100 HP
Thorin attacks for 15 damage
Thorin takes 12 damage
Thorin: 88/100 HP
Thorin takes 92 damage

И для входных данных:

mage
Gandalf
80
25
10
6
attack
useability
setability fire 30
useability
setability ice 25
useability
defend 40

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

Gandalf attacks for 50 damage
No ability set
Casts fireball for 30 damage
Casts ice shard for 25 damage
Gandalf takes 35 damage

И для входных данных:

archer
Legolas
90
18
15
4
status
attack
defend 24
status

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

Legolas: 90/90 HP
Legolas attacks for 23 damage
Legolas takes 18 damage
Legolas: 72/90 HP

Обратите внимание, как встраивание структур позволяет каждому типу персонажа использовать общие поля и методы базового Character, в то время как интерфейсы обеспечивают полиморфный бой, где любой Attacker может наносить урон, а любой Defender — получать его. Паттерн «Стратегия» отлично проявляет себя в сменных способностях мага — один и тот же персонаж может использовать разные заклинания без изменения своей основной реализации!

Попробуйте сами

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	scanner := bufio.NewScanner(os.Stdin)

	// Считать тип персонажа
	scanner.Scan()
	charType := strings.TrimSpace(scanner.Text())

	// Считать имя персонажа
	scanner.Scan()
	name := strings.TrimSpace(scanner.Text())

	// Считать здоровье
	scanner.Scan()
	health, _ := strconv.Atoi(strings.TrimSpace(scanner.Text()))

	// Считать первый специфический для типа параметр
	scanner.Scan()
	stat1, _ := strconv.Atoi(strings.TrimSpace(scanner.Text()))

	// Считать второй специфический для типа параметр
	scanner.Scan()
	stat2, _ := strconv.Atoi(strings.TrimSpace(scanner.Text()))

	// TODO: Создать соответствующего персонажа на основе charType
	// Использовать переменные: charType, name, health, stat1, stat2
	// Для warrior: stat1 = Strength, stat2 = Armor
	// Для mage: stat1 = Intelligence, stat2 = MagicResist
	// Для archer: stat1 = Agility, stat2 = Evasion

	// Считать количество действий
	scanner.Scan()
	numActions, _ := strconv.Atoi(strings.TrimSpace(scanner.Text()))

	// Обработать каждое действие
	for i := 0; i < numActions; i++ {
		scanner.Scan()
		line := strings.TrimSpace(scanner.Text())
		parts := strings.Fields(line)
		action := parts[0]

		// TODO: Обработать каждый тип действия:
		// - "status": вывести Status() персонажа
		// - "attack": вывести "[Name] attacks for [damage] damage"
		// - "defend [amount]": применить урон и вывести "[Name] takes [actual] damage"
		// - "setability [type] [power]": для магов, установить способность (fire, ice или strike)
		// - "useability": для магов, вывести результат UseAbility()

		_ = action // Удалите эту строку при реализации
		_ = fmt.Println // Удалите эту строку при реализации
	}
}

Все уроки раздела Объектно-ориентированное программирование

16Финальные испытания

Платформа онлайн-обученияБанковская системаСистема игровых персонажей