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

تطوير شخصيات الألعاب

جزء من قسم Object Oriented Programming في رحلة Java على Coddy — الدرس 86 من 87.

يتطلب منك هذا التحدي بناء نظام تطوير شخصيات الألعاب يستعرض قوة البرمجة كائنية التوجه (OOP) في نمذجة كيانات معقدة وتفاعلية.

صمم تسلسلاً هرمياً للشخصيات حيث تحدد فئة Character الأساسية سمات مشتركة مثل الصحة، والاسم، والمستوى. تقوم فئات متخصصة مثل Warrior و Mage و Archer بتوسيع هذه الفئة الأساسية بقدرات وأساليب قتالية فريدة.

تعمل الواجهات بشكل طبيعي هنا: يمكن لـ Attackable تحديد أساليب القتال، بينما يتولى Healable معالجة قدرات الاستعادة. قد يقوم Mage بتنفيذ كليهما، في حين يركز Warrior فقط على الهجوم.

فكر في استخدام نمط الاستراتيجية (Strategy pattern) لسلوكيات الهجوم المختلفة، مما يسمح للشخصيات بتبديل أساليب القتال بشكل ديناميكي. يمكن لنمط الحالة (State pattern) إدارة حالات الشخصية مثل الحالات الطبيعية، أو المسمومة، أو المذهولة التي تؤثر على السلوك.

فكر في استخدام التركيب (composition) لأنظمة المعدات حيث "تمتلك" الشخصيات أسلحة ودروعاً بدلاً من الوراثة منها. استخدم enums لفئات الشخصيات أو أنواع الضرر، وقم بتطبيق encapsulation لحماية الإحصائيات من التعديلات غير الصالحة.

challenge icon

التحدي

سهل

لنقم ببناء نظام تطوير شخصيات ألعاب يستعرض قوة البرمجة كائنية التوجه (OOP) في نمذجة كيانات الألعاب المعقدة والتفاعلية! ستقوم بإنشاء تسلسل هرمي للشخصيات بأنماط قتالية مختلفة، وقدرات خاصة، ونظام حالة يؤثر على سلوك الشخصيات.

ستقوم بتنظيم الكود الخاص بك عبر سبعة ملفات:

  • DamageType.java: أنشئ enum يمثل أنواعاً مختلفة من الضرر في اللعبة. قم بتضمين القيم PHYSICAL، و MAGICAL، و RANGED. أضف حقلاً خاصاً description (String)، ومنشئاً (constructor) يقوم بضبطه، وطريقة getter. يجب أن يكون للضرر الجسدي الوصف "brute force"، وللسحري "arcane energy"، وللمدى البعيد "precision strike".
  • Attackable.java: أنشئ واجهة (interface) تحدد القدرات القتالية. صرّح عن الطرق attack(Character target) التي تعيد String يصف الهجوم، و getDamageType() التي تعيد DamageType.
  • Healable.java: أنشئ واجهة لقدرات الاستشفاء. صرّح عن طريقة heal(int amount) تعيد String يصف إجراء الشفاء.
  • Character.java: أنشئ فئة أساسية مجردة (abstract base class) لجميع شخصيات اللعبة. قم بتضمين حقول خاصة لـ name (String)، و health (int)، و maxHealth (int)، و level (int). يأخذ المنشئ name، و maxHealth، و level، ويضبط health ليكون مساوياً لـ maxHealth في البداية. قم بتضمين getters لجميع الحقول. أضف طريقة محمية (protected) باسم setHealth(int health) تضمن بقاء الصحة بين 0 و maxHealth. أنشئ طريقة takeDamage(int damage) تقلل الصحة وتعيد "[name] takes [damage] damage! Health: [health]/[maxHealth]". أضف طريقة isAlive() تعيد true إذا كانت الصحة أكبر من 0. صرّح عن طريقة مجردة getCharacterClass() تعيد String.
  • Warrior.java: أنشئ فئة ترث من Character وتنفذ Attackable. أضف حقلاً خاصاً strength (int). يأخذ المنشئ name، و maxHealth، و level، و strength. قم بتنفيذ getCharacterClass() لتعيد "Warrior". قم بتنفيذ getDamageType() لتعيد PHYSICAL. قم بتنفيذ attack(Character target) لإلحاق ضرر يساوي strength زائد level، واستدعاء طريقة takeDamage للهدف، وإعادة "[name] strikes with [damageType description] for [damage] damage!" متبوعاً بسطر جديد ونتيجة takeDamage.
  • Mage.java: أنشئ فئة ترث من Character وتنفذ كلاً من Attackable و Healable. أضف حقولاً خاصة intelligence (int) و mana (int). يأخذ المنشئ name، و maxHealth، و level، و intelligence، و mana. قم بتنفيذ getCharacterClass() لتعيد "Mage". قم بتنفيذ getDamageType() لتعيد MAGICAL. قم بتنفيذ attack(Character target) لإلحاق ضرر يساوي intelligence مضروباً في 2، باتباع نفس تنسيق Warrior. قم بتنفيذ heal(int amount) لاستعادة الصحة (باستخدام setHealth) وإعادة "[name] channels healing magic! Health: [health]/[maxHealth]".
  • Main.java: ابعث الحياة في نظام لعبتك! ستتلقى سلسلة نصية من الأوامر مفصولة بفاصلة:
    • CREATE_WARRIOR:name:maxHealth:level:strength
    • CREATE_MAGE:name:maxHealth:level:intelligence:mana
    • ATTACK:attackerName:targetName
    • HEAL:mageName:amount
    • STATUS:characterName

    احتفظ بمجموعة من الشخصيات. قم بمعالجة كل أمر واطبع:

    • CREATE_WARRIOR/CREATE_MAGE: [name] the [characterClass] joins the battle!
    • ATTACK: اطبع نتيجة الهجوم (السلسلة النصية التي تعيدها طريقة attack)
    • HEAL: اطبع نتيجة الشفاء، أو [name] cannot heal إذا لم تكن الشخصية Mage
    • STATUS: [name] ([characterClass]) - Level [level] - Health: [health]/[maxHealth] - [Alive/Defeated]

    بعد كل الأوامر، اطبع --- Battle Summary --- متبوعاً بحالة كل شخصية.

ستتلقى مدخلاً واحداً: سلسلة أوامر مفصولة بفاصلة.

على سبيل المثال، مع المدخل CREATE_WARRIOR:Thorin:100:5:15,CREATE_MAGE:Gandalf:80:7:12:50,ATTACK:Thorin:Gandalf,HEAL:Gandalf:25,STATUS:Gandalf، سيكون مخرجك:

Thorin the Warrior joins the battle!
Gandalf the Mage joins the battle!
Thorin strikes with brute force for 20 damage!
Gandalf takes 20 damage! Health: 60/80
Gandalf channels healing magic! Health: 80/80
Gandalf (Mage) - Level 7 - Health: 80/80 - Alive
--- Battle Summary ---
Thorin (Warrior) - Level 5 - Health: 100/100 - Alive
Gandalf (Mage) - Level 7 - Health: 80/80 - Alive

يجمع هذا التحدي بين الوراثة (تسلسل Character الهرمي)، وتنفيذ واجهات متعددة (Mage ينفذ كلاً من Attackable و Healable)، والـ enums مع الطرق (DamageType)، وتعدد الأشكال (التعامل مع أنواع الشخصيات المختلفة بشكل موحد)، والتغليف (إدارة الصحة المحمية) في نظام لعبة ممتع!

ورقة مرجعية

تسمح البرمجة كائنية التوجه (OOP) بنمذجة الأنظمة المعقدة من خلال الفئات (classes)، والوراثة (inheritance)، والواجهات (interfaces)، وأنماط التصميم (design patterns).

التسلسل الهرمي للفئات

قم بإنشاء فئة أساسية بخصائص مشتركة وقم بتوسيعها بفئات متخصصة:

public abstract class Character {
    private String name;
    private int health;
    private int maxHealth;
    private int level;
    
    public Character(String name, int maxHealth, int level) {
        this.name = name;
        this.maxHealth = maxHealth;
        this.health = maxHealth;
        this.level = level;
    }
    
    protected void setHealth(int health) {
        this.health = Math.max(0, Math.min(health, maxHealth));
    }
    
    public abstract String getCharacterClass();
}

الواجهات (Interfaces)

حدد العقود لسلوكيات معينة يمكن للفئات تنفيذها:

public interface Attackable {
    String attack(Character target);
    DamageType getDamageType();
}

public interface Healable {
    String heal(int amount);
}

التعدادات (Enums) مع الحقول

يمكن أن تحتوي التعدادات على حقول، ومنشئات (constructors)، وطرق (methods):

public enum DamageType {
    PHYSICAL("brute force"),
    MAGICAL("arcane energy"),
    RANGED("precision strike");
    
    private String description;
    
    private DamageType(String description) {
        this.description = description;
    }
    
    public String getDescription() {
        return description;
    }
}

تنفيذ واجهات متعددة

يمكن لفئة واحدة تنفيذ واجهات متعددة:

public class Mage extends Character implements Attackable, Healable {
    private int intelligence;
    private int mana;
    
    @Override
    public String attack(Character target) {
        // التنفيذ
    }
    
    @Override
    public String heal(int amount) {
        // التنفيذ
    }
}

التغليف (Encapsulation)

استخدم الحقول الخاصة (private fields) مع أدوات التعيين المحمية (protected setters) للتحكم في الوصول والتحقق من صحة البيانات:

protected void setHealth(int health) {
    this.health = Math.max(0, Math.min(health, maxHealth));
}

تعدد الأشكال (Polymorphism)

تعامل مع أنواع الشخصيات المختلفة بشكل موحد من خلال فئتها الأساسية المشتركة أو واجهاتها، مما يسمح بمجموعات مرنة واستدعاءات للطرق.

جرّب بنفسك

import java.util.Scanner;
import java.util.HashMap;
import java.util.Map;
import java.util.LinkedHashMap;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String input = scanner.nextLine();
        
        // TODO: استخدم مجموعة (collection) للحفاظ على الشخصيات (يحافظ LinkedHashMap على ترتيب الإدخال)
        // LinkedHashMap<String, Character> characters = new LinkedHashMap<>();
        
        // TODO: قم بتقسيم المدخلات بواسطة الفاصلة للحصول على الأوامر الفردية
        // String[] commands = input.split(",");
        
        // TODO: معالجة كل أمر:
        // - CREATE_WARRIOR:name:maxHealth:level:strength
        //   اطبع: "[name] the Warrior joins the battle!"
        // 
        // - CREATE_MAGE:name:maxHealth:level:intelligence:mana
        //   اطبع: "[name] the Mage joins the battle!"
        // 
        // - ATTACK:attackerName:targetName
        //   اطبع نتيجة الهجوم من الدالة attack
        // 
        // - HEAL:mageName:amount
        //   اطبع نتيجة العلاج، أو "[name] cannot heal" إذا لم يكن Mage
        // 
        // - STATUS:characterName
        //   اطبع: "[name] ([characterClass]) - Level [level] - Health: [health]/[maxHealth] - [Alive/Defeated]"
        
        // TODO: بعد كل الأوامر، اطبع "--- Battle Summary ---"
        // ثم اطبع حالة كل شخصية
    }
}
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس Object Oriented Programming