Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

نظام شخصيات الألعاب

جزء من قسم البرمجة كائنية التوجه في رحلة GO على Coddy. الدرس 107 من 107.

challenge icon

التحدي

سهل

لنبنِ نظام شخصيات للعبة يجمع بين تضمين البنى، والواجهات، ونمط الاستراتيجية لإنشاء آليات قتال مرنة! ستصمم أنواعًا مختلفة من الشخصيات يمكنها الهجوم والدفاع بطرق فريدة، مع قدرات يمكن تبديلها أثناء التشغيل.

ستنظم شيفرتك عبر خمسة ملفات:

  • character.go: عرّف بنية Character أساسية تحتوي على الحقول common: Name (string)، وHealth (int)، وMaxHealth (int). أدرج مُنشئًا باسم NewCharacter والطرائق التالية:
    • IsAlive() bool: تُرجع true إذا كانت الصحة أكبر من 0
    • Status() string: تُرجع التنسيق: [Name]: [Health]/[MaxHealth] HP
  • interfaces.go: عرّف واجهات القتال التي تتيح تعدد الأشكال:
    • واجهة Attacker مع Attack() int: تُرجع مقدار الضرر dealt
    • واجهة Defender مع TakeDamage(damage int) int: تطبّق تقليل الضرر وتُرجع مقدار الضرر actual المتلقّى
    • واجهة 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 إذا كانت ability تساوي nil.

  • main.go: أنشئ الشخصيات واستعرض آليات القتال.

    اقرأ نوع الشخصية (warrior أو mage أو archer)، ثم اقرأ اسم الشخصية وصحتها وإحصاءاتها الخاصة بالنوع. أنشئ الشخصية appropriate.

    ثم اقرأ عدد actions. كل action هو أحد الخيارات التالية:

    • status: اطبع حالة الشخصية
    • attack: اطبع [Name] attacks for [damage] damage
    • defend [amount]: طبّق الضرر واطبع [Name] takes [actual] damage
    • setability [type] [power]: بالنسبة إلى السحرة فقط، عيّن القدرة (النوع هو fire أو ice أو strike)
    • useability: بالنسبة إلى السحرة فقط، اطبع نتيجة Use() الخاصة بالقدرة

ستُقدَّم المدخلات التالية:

  • نوع الشخصية واسمها وصحتها وإحصاءاتها الخاصة بالنوع
  • عدد actions، ثم كل action في سطر منفصل

على سبيل المثال، عند إعطاء:

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 تلقّيه. ويتألق نمط الاستراتيجية مع قدرات Mage القابلة للتبديل: إذ يمكن للشخصية نفسها استخدام تعاويذ مختلفة دون تغيير تطبيقها الأساسي!

جرّب بنفسك

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, or strike)
		// - "useability": للسحرة، اطبع نتيجة UseAbility()

		_ = action // احذف هذا السطر عند التنفيذ
		_ = fmt.Println // احذف هذا السطر عند التنفيذ
	}
}

جميع دروس البرمجة كائنية التوجه

16التحديات النهائية

منصة تعليم إلكترونينظام بنكينظام شخصيات الألعاب

تدرّب بنفسك: مترجم Go عبر الإنترنت