অনেক গুণাবলীর সাথে হিরোর জন্য ওওপি আর্কিটেকচার


14

আমি একটি সাধারণ ব্রাউজার পাঠ্য আরপিজি শুরু করতে চলেছি, এমন অক্ষরগুলি সহ যা (প্যাসিভলি) অন্যান্য লোকের সাথে লড়াই করতে পারে। এটি বিভিন্ন অস্ত্রের জন্য অতিরিক্ত দক্ষতার সাথে শক্তি, দক্ষতা এবং আরও প্রায় 10 টি দক্ষতার একটি তালিকা জড়িত।

এই চরিত্রের শ্রেণীর নকশা করার কি আরও ভাল উপায় আছে তবে ক্লাস অ্যাট্রিবিউট হিসাবে কেবল সেই দক্ষতা রয়েছে? এটি সহজ বলে মনে হচ্ছে তবে আমি অনিচ্ছা কারণ এটি আনাড়ি।

class Char(self):
    int strength
    int dexterity
    int agility
    ...
    int weaponless
    int dagger
    ...

1
গেমগুলি লেখার জন্য এবং কিছু সাধারণ শ্রেণীর মধ্যে কীভাবে লিঙ্কটি
ড্রাগন

@ ড্রাগন আকর্ষণীয় লিঙ্কটির জন্য ধন্যবাদ, তবে আমি Charactorক্লাসটি ডিজাইনের জন্য আরও গভীর ব্যাখ্যা দেখতে পাচ্ছি না ?
সোভেন

1
এই নকশাটি সম্পর্কে আপনি "আনাড়ি" ঠিক কী আবিষ্কার করেন?
টমাস

উত্তর:


17

যতক্ষণ আপনি আপনার সিস্টেমকে তুলনামূলকভাবে সহজ রাখেন, এটি কাজ করা উচিত। আপনি যখন অস্থায়ী দক্ষতা সংশোধকগুলির মতো জিনিস যুক্ত করবেন, আপনি শীঘ্রই প্রচুর নকল কোড দেখতে পাবেন। আপনি বিভিন্ন দক্ষতা ব্যবহার করে বিভিন্ন অস্ত্র নিয়েও সমস্যায় পড়বেন। যেহেতু প্রতিটি দক্ষতা একটি পৃথক পরিবর্তনশীল, তাই আপনাকে প্রতিটি দক্ষতা-টাইপের জন্য আলাদা আলাদা কোড লিখতে হবে যা মূলত একই রকম হয় (বা কিছু কুৎসিত প্রতিচ্ছবি হ্যাক ব্যবহার করুন - আপনার প্রোগ্রামিং ভাষাটি তাদের সমর্থন করে এমন শর্তে)।

সেই কারণে আমি আপনাকে দক্ষতা এবং দক্ষতা উভয়ই একটি সংযুক্ত ডেটা স্ট্রাকচারে সঞ্চয় করার জন্য সুপারিশ করব যা দক্ষতা-ধ্রুবককে মানগুলিতে মানচিত্র করে। কীভাবে এটি করবেন তা প্রোগ্রামিং ভাষার থেকে প্রোগ্রামিং ভাষার থেকে আলাদা leg আপনার ভাষা যখন এটি সমর্থন করে, তখন ধ্রুবকগুলি একটিতে থাকা উচিত enum

এটি অনুশীলনে কীভাবে কাজ করবে তা উদাহরণ দেওয়ার জন্য, আক্রমণ ক্ষতির গণনা করার জন্য আপনার কোডটি এর পরে এর মতো কিছু দেখবে:

int damage = attacker.getSkill(STRENGTH) + 
             attacker.getProficiency(weapon.getProficiencyRequired()) -
             defender.getSkill(TOUGHNESS);

এই জাতীয় পদ্ধতি তৈরি করা অবজেক্ট-ওরিয়েন্টেড প্রোগ্রামিংয়ের মৌলিক নীতিরgetSkill() বিরুদ্ধে যায় ।
যিফির

4

কেন যুক্ত অ্যারে ব্যবহার করবেন না ?, এটি সহজে প্রসারিত হওয়ার সুবিধা দেয় (উদাহরণস্বরূপ পিএইচপি ব্যবহার করে)

$Stats["Strength"] = "8";
$Stats["Dexterity"] = "8";

অস্ত্র যেমন জিনিসগুলির জন্য, আপনি সম্ভবত কিছু বেস ক্লাস তৈরি করতে চাইবেন

অস্ত্র -> মেলিওয়েপন, রেঞ্জড ওয়েপন

এবং তারপরে সেখান থেকে আপনার অস্ত্র তৈরি করুন।

আমি শেষ ফলাফলটির জন্য লক্ষ্য করব এটি একটি শ্রেণীর মতো দেখাচ্ছে

class Character
{
    public $Stats;
    public $RightHand;
    public $LeftHand;
    public $Armor;
    public $Name;
    public $MaxHealth;
    public $CurrentHealth;

    public function __construct()
    {
        //Basic
        $this->Name = "Fred";
        $this->MaxHealth = "10";
        $this->CurrentHealth = "10";

        //Stats
        $this->Stats["Strength"] = 8;
        $this->Stats["Dexterity"] = 8;
        $this->Stats["Intellect"] = 8;
        $this->Stats["Constitution"] = 8;

        //Items
        $this->RightHand = NULL;
        $this->LeftHand  = NULL;
        $this->Armor = NULL;

    }
}

আপনি যদি সত্যিই খুব চান তবে আপনি সমস্ত কিছু অ্যারেতে সঞ্চয় করতে পারেন।


@ ফিলিপ কী বলেছিলেন তা কি অনেকটাই?
আতুরস্যামস

1
@ ফিলিপ এনাম ব্যবহারের পরামর্শ দিয়েছিল, অ্যারে অন্য বিকল্প।
গ্রিমস্টন

এটি আসলে বলে: "... দক্ষ তথ্য-কাঠামো যা দক্ষতা-ধ্রুবককে মানগুলিতে মানচিত্র করে", অভিধানের ধ্রুবকগুলি স্ট্রিং হতে পারে।
আতুরস্যামস

3

আমি এই প্রশ্নের উত্তর সর্বাধিক ওওপি উপায় দিয়ে দেওয়ার চেষ্টা করব (বা কমপক্ষে আমার কী মনে হয় এটি হবে)। আপনি পরিসংখ্যান সম্পর্কে যে বিবর্তন দেখছেন তার উপর নির্ভর করে এটি সম্পূর্ণ ওভারকিল হতে পারে।

আপনি কোনও স্কিলসেট (বা পরিসংখ্যান ) শ্রেণীর কল্পনা করতে পারেন (আমি এই উত্তরের জন্য সি-জাতীয় সিনট্যাক্স ব্যবহার করছি):

class SkillSet {

    // Consider better data encapsulation
    int strength;
    int dexterity;
    int agility;

    public static SkillSet add(SkillSet stats) {
        strength += stats.strength;
        dexterity += stats.dexterity;
        agility += stats.agility;
    }

    public static SkillSet apply(SkillModifier modifier) {
        strength *= modifier.getStrengthModifier();
        dexterity *= modifier.getDexterityModifier();
        agility *= modifier.getAgilityModifier();

    }

}

তারপরে নায়কের স্কিলসেট ধরণের একটি অন্তর্নিহিত স্ট্যাটাস ক্ষেত্র থাকবে। একটি অস্ত্রের পাশাপাশি একটি পরিবর্তনকারী দক্ষতাও থাকতে পারে।

public abstract class Hero implements SkillSet {

    SkillSet intrinsicStats;
    Weapon weapon;

    public SkillSet getFinalStats() {
        SkillSet finalStats;
        finalStats = intrinsicStats;
        finalStats.add(weapon.getStats());
        foreach(SkillModifier modifier : getEquipmentModifiers()) {
            finalStats.apply(modifier);
        }
        return finalStats;
    }

    protected abstract List<SkillModifier> getEquipmentModifiers();

}

এটি অবশ্যই আপনাকে ধারণা দেওয়ার জন্য একটি উদাহরণ। আপনি ডেকোরেটর ডিজাইন প্যাটার্নটি ব্যবহার করেও বিবেচনা করতে পারেন, যাতে পরিসংখ্যানগুলির সংশোধকগুলি "ফিল্টার" হিসাবে কাজ করে যা একের পর এক প্রয়োগ করা হয় ...


এই সি-এর মতো কেমন?
বগলেজ

@ বোগ্লেজ: আমি একইভাবে সিউডোকোডকে উল্লেখ করার জন্য "সি'শ" ব্যবহার করার প্রবণতা ব্যবহার করি যা ক্লাসে জড়িত থাকলেও, শিথিলভাবে একটি কোঁকড়ানো-ব্রেস ভাষার সাথে সাদৃশ্যপূর্ণ। আপনার একটি বক্তব্য রয়েছে, যদিও: এটি আরও নির্দিষ্ট সিনট্যাক্সের মতো দেখায় - এটি সামান্য পরিবর্তন বা জাভা সংকলনযোগ্য হওয়া থেকে দু'দিক দূরে।
সিএওও

আমি মনে করি না যে আমি এখানে অত্যধিক কঠোর হচ্ছি। এটি কেবল সিনট্যাক্সের পার্থক্য নয়, শব্দার্থবিজ্ঞানের পার্থক্য। সি তে কোনও শ্রেণি, টেম্পলেট, সুরক্ষিত-যোগ্যতা অর্জনকারী, পদ্ধতি, ভার্চুয়াল ফাংশন ইত্যাদির মতো জিনিস নেই আমি শর্তাদির এই নৈমিত্তিক অপব্যবহারের পক্ষে শুধু পছন্দ করি না।
বগলেজ

1
অন্যরা যেমন বলেছে, কোঁকড়ানো-ব্রেস সিনট্যাক্স সি থেকে এসেছে জাভাটির বাক্য গঠন (বা সেই বিষয়ে সি #) এই শৈলীতে অত্যন্ত অনুপ্রাণিত।
পিয়ের আরলাড 20'14

3

জিনিসগুলি করার সবচেয়ে ওওপি উপায় সম্ভবত উত্তরাধিকারের সাথে কিছু করা। আপনার বেস ক্লাস (বা ভাষার উপর নির্ভর করে সুপার ক্লাস) ব্যক্তি হতে হবে, তবে সম্ভবত ভিলেন এবং নায়করা বেস ক্লাস থেকে উত্তরাধিকারী। তারপরে আপনার শক্তি ভিত্তিক নায়ক এবং ফ্লাইট ভিত্তিক নায়করা তাদের পরিবহণের ধরনটি আলাদা হওয়ায় শাখাটি বন্ধ হয়ে যায়। এটিতে যুক্ত বোনাস রয়েছে যে আপনার কম্পিউটার প্লেয়ারদের মানব খেলোয়াড়ের মতো একই বেস ক্লাস থাকতে পারে এবং এটি আশা করি আপনার জীবন সহজ করবে।

বৈশিষ্ট্যগুলি সম্পর্কিত অন্যান্য জিনিস, এবং এটি কম OOP নির্দিষ্ট হ'ল তালিকা হিসাবে আপনার চরিত্রের বৈশিষ্ট্যগুলি উপস্থাপন করা হবে যাতে আপনার কোডগুলিতে সেগুলি সমস্ত স্পষ্টভাবে সংজ্ঞায়িত করা উচিত নয়। সুতরাং আপনার কাছে অস্ত্রগুলির একটি তালিকা এবং শারীরিক বৈশিষ্ট্যের জন্য একটি তালিকা থাকবে। এই বৈশিষ্ট্যগুলির জন্য কিছু ধরণের বেস শ্রেণি তৈরি করুন যাতে তারা মিথস্ক্রিয়া করতে পারে, তাই প্রত্যেককে ক্ষতি, শক্তি ব্যয় ইত্যাদির ক্ষেত্রে সংজ্ঞায়িত করা হয় সুতরাং যখন দুটি ব্যক্তি একত্রিত হয় তখন এটি কীভাবে ইন্টারঅ্যাকশনটি ঘটবে তা অপেক্ষাকৃত স্পষ্ট। আপনি প্রতিটি চরিত্রের বৈশিষ্ট্যগুলির তালিকার তালিকার মধ্য দিয়ে পুনরাবৃত্তি করতে পারবেন এবং প্রতিটি মিথস্ক্রিয়াতে সম্ভাবনার একটি ডিগ্রি দিয়ে অন্যটির সাথে যে ক্ষতির সম্ভাবনা রয়েছে তা গণনা করবেন।

একটি তালিকা ব্যবহার করা আপনাকে প্রচুর কোডের পুনর্লিখন এড়াতে সহায়তা করবে কারণ আপনি যে বৈশিষ্ট্যটি এখনও ভাবেননি সেটির সাথে একটি চরিত্র যুক্ত করতে, আপনাকে কেবল এটি নিশ্চিত করতে হবে যে এটির একটি ইন্টারঅ্যাকশন রয়েছে যা আপনার বিদ্যমান সিস্টেমের সাথে কাজ করে।


4
আমি মনে করি বিন্দুটি হিরো ক্লাসের পরিসংখ্যানগুলিকে দ্বিগুণ করা। উত্তরাধিকারসূত্রে অগত্যা সেরা ওওপি সমাধান নয় (আমার উত্তরে আমি এর পরিবর্তে রচনাটি ব্যবহার করেছি)।
পিয়ের আরলাড

1
আমি আগের মন্তব্য দ্বিতীয়। একটি অক্ষরের সি এবং এ থেকে বি চরিত্রের বৈশিষ্ট্য (যা উভয়ের একই ভিত্তি শ্রেণি রয়েছে) কী ঘটবে? আপনি হয় কোড নকল বা একাধিক উত্তরাধিকার সংক্রান্ত কিছু সমস্যার সম্মুখীন । আমি এক্ষেত্রে উত্তরাধিকারের তুলনায় রচনাটির পক্ষে চাই।
কমফ্রিচ

2
যথেষ্ট ফর্সা। আমি কেবল ওপিকে কিছু বিকল্প দিচ্ছিলাম। দেখে মনে হচ্ছে না এই পর্যায়ে পাথরের অনেকগুলি সেট রয়েছে এবং আমি তাদের অভিজ্ঞতার স্তরটি জানি না। কোনও শিক্ষানবিস সম্পূর্ণ প্রস্ফুটিত বহুবৈচিত্র্যটি টেনে আনার প্রত্যাশা করা সম্ভবত কিছুটা হলেও, উত্তরাধিকার সূচনা করার পক্ষে উত্তরাধিকার যথেষ্ট সহজ। কোডটি 'আনাড়ি' বোধের সমস্যাটি সমাধান করার জন্য আমি সাহায্য করার চেষ্টা করছিলাম যা আমি কেবল ধরে নিতে পারি যা ক্ষেত্রগুলিতে হার্ড কোডিং রয়েছে যা ব্যবহারে আসতে পারে বা নাও পারে to এই জাতীয় অপরিশোধিত মানগুলির জন্য একটি তালিকা ব্যবহার করা ভাল একটি বিকল্প।
জেনেরিকাম

1
-1: "জিনিসগুলি করার সবচেয়ে ওওপি উপায় সম্ভবত উত্তরাধিকারের সাথে কিছু করা।" উত্তরাধিকার বিশেষত বস্তু-কেন্দ্রিক নয়।
শান মিডলডিচ

3

আমি স্ট্যাচ টাইপ ম্যানেজারের পরামর্শ দেব, একটি ডেটা ফাইল থেকে উদ্ভূত (যেমন আমি এক্সএমএল ব্যবহার করি) এবং স্ট্যাট অবজেক্টস, হ্যাশট্যাবল হিসাবে অক্ষরের অন্তর্নিহিত অক্ষরটিতে টাইপ এবং মান সহ, কী হিসাবে স্ট্যাট টাইপের অনন্য আইডি রয়েছে।

সম্পাদনা করুন: স্যুডো কোড

Class StatType
{
    int ID;
    string Name;

    public StatType(int _id, string _name)
    {
        ID = _id;
        Name = _name;
    }
}


Class StatTypeManager
{
    private static Hashtable statTypes;

    public static void Init()
    {
        statTypes = new Hashtable();

        StatType type;

        type = new StatType(0, "Strength");
        statTypes.add(type.ID, type);

        type = new StatType(1, "Dexterity");
        statTypes.add(type.ID, type);

        //etc

        //Recommended: Load your stat types from an external resource file, e.g. xml
    }

    public static StatType getType(int _id)
    {
        return (StatType)statTypes[_id];
    }
}

class Stat
{
    StatType Type;
    int Value;

    public Stat(StatType _type, int _value)
    {
        Type = _type;
        Value = _value;
    }
}

Class Char
{
    Hashtable Stats;

    public Char(Stats _stats)
    {
        Stats = _stats;
    }

    public int GetStatValue(int _id)
    {
        return ((Stat)Stats[_id]).Value;
    }
}

আমি মনে করি StatTypeবর্গ অপ্রয়োজনীয় মধ্যে শুধু ব্যবহার nameএর StatTypeএকটি কী হিসাবে। যেমনটি # গ্রিমস্টন করেছে। একই সঙ্গে Stats
জিয়ানিস ক্রিসটোফাকিস

আমি এরকম উদাহরণগুলিতে ক্লাস ব্যবহার করতে পছন্দ করি যাতে আপনি অবাধে নামটি সংশোধন করতে পারেন (যখন আইডিটি স্থির থাকে)। এই উদাহরণে ওভারকিল? সম্ভবত, তবে যেহেতু এই কৌশলটি অন্য কোনও প্রোগ্রামের জন্য অন্য কোথাও ব্যবহার করা যেতে পারে আমি এটির মতো করে এটির মতো করতাম।
ডিফ্রিমন

0

আমি আপনার অস্ত্রাগার এবং আপনার অস্ত্রাগারটি কীভাবে ডিজাইন করতে পারি তার একটি উদাহরণ দেওয়ার চেষ্টা করব।

আমাদের লক্ষ্য সত্তাকে ডিকুয়াল করা, সুতরাং অস্ত্রটি একটি ইন্টারফেস হওয়া উচিত।

interface Weapon {
    public int getDamage();
}

মনে করুন যে প্রতিটি খেলোয়াড় কেবল একটি অস্ত্র রাখতে পারে, আমরা Strategy patternসহজেই অস্ত্রগুলি পরিবর্তন করতে ব্যবহার করতে পারি ।

class Knife implements Weapon {
    private int damage = 10;
    @Override
    public int getDamage() {
        return this.damage;
    }
}

class Sword implements Weapon {
    private int damage = 40;
    @Override
    public int getDamage() {
        return this.damage;
    }
}

খেলোয়াড় নিরস্ত্র হওয়ার ক্ষেত্রে আর একটি দরকারী প্যাটার্ন হ'ল নাল অবজেক্ট প্যাটার্ন

class Weaponless implements Weapon {
    private int damage = 0;
    @Override
    public int getDamage() {
        return this.damage;
    }
}

অস্ত্রাগার হিসাবে, আমরা একাধিক প্রতিরক্ষা সরঞ্জাম পরতে পারেন।

// Defence classes,interfaces

interface Armor {
    public int defend();
}

class Defenseless implements Armor {

    @Override
    public int defend() {
        return 0;
    }
}

abstract class Armory implements Armor {

    private Armor armory;
    protected int defence;

    public Armory() {
        this(new Defenseless());
    }

    public Armory(Armor force) {
        this.armory = force;
    }

    @Override
    public int defend() {
        return this.armory.defend() + this.defence;
    }

}

// Defence implementations

class Helmet extends Armory {
    {
        this.defence = 30;
    }    
}

class Gloves extends Armory {
    {
        this.defence = 10;
    }    
}

class Boots extends Armory {
    {
        this.defence = 10;
    }    
}

ডিকপলিংয়ের জন্য, আমি ডিফেন্ডারের জন্য একটি ইন্টারফেস তৈরি করেছি।

interface Defender {
    int getDefended();
}

এবং Playerক্লাস।

class Player implements Defender {

    private String title;

    private int health = 100;
    private Weapon weapon = new Weaponless();
    private List<Armor> armory = new ArrayList<Armor>(){{ new Defenseless(); }};


    public Player(String name) {
        this.title = name;
    }

    public Player() {
        this("John Doe");
    }

    public String getName() {
        return this.title;
    }


    public void setWeapon(Weapon weapon) {
        this.weapon = weapon;
    }

    public void attack(Player enemy) {

        System.out.println(this.getName() + " attacked " + enemy.getName());

        int attack = enemy.getDefended() + enemy.getHealth()- this.weapon.getDamage();

        int health = Math.min(enemy.getHealth(),attack);

        System.out.println("After attack " + enemy.getName() + " health is " + health);

        enemy.setHealth(health);
    }

    public int getHealth() {
        return health;
    }

    private void setHealth(int health) {
        /* Check for die */
        this.health = health;
    }

    public void addArmory(Armor armor) {
        this.armory.add(armor);
    }


    @Override
    public int getDefended() {
        int defence = this.armory.stream().mapToInt(armor -> armor.defend()).sum();
        System.out.println(this.getName() + " defended , armory points are " + defence);
        return defence;
    }

}

আসুন কিছু গেমপ্লে যুক্ত করি।

public class Game {
    public static void main(String[] args) {
        Player yannis = new Player("yannis");
        Player sven = new Player("sven");


        yannis.setWeapon(new Knife());
        sven.setWeapon(new Sword());


        sven.addArmory(new Helmet());
        sven.addArmory(new Boots());

        yannis.attack(sven);      
        sven.attack(yannis);      
    }
}

ভাল খবর!


2
এই উত্তরটি আরও সহায়ক হবে যখন আপনি নিজের ডিজাইনের পছন্দগুলির পিছনে যুক্তিটি ব্যাখ্যা করবেন।
ফিলিপ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.