Home>

I want to sort the processing by the character string, but if I write it for switch, the code becomes long.
How can you make your code smarter?

Features I want to implement

An application that simulates character movement. (Something like)

There are the following tables in the database, and calculate them to change the character's behavior.

key (string) Value
WalkSpeed ​​ +10
WalkSpeed ​​ +20
WalkSpeed ​​ -10
AttackSpeed ​​ +5
AttackSpeed ​​ +10
IsPoison 1
// Each row of the table
public class DataUnit {
    string Key {get;set;}
    float Value {get;set;}
    public DataUnit (string key, float value) {
        Key = key;
        Value = value;
    }
}
public class Chara {
    float walkSpeed ​​= 0f;
    float attackSpeed ​​= 0f;
    bool isPoison = false;
    void TestFunc () {
        List<DataUnit>dataUnits = new List<DataUnit>();
        // Save the table data from the database to dataUnits (the following generates data for debugging)
        dataUnits.Add (new DataUnit ("WalkSpeed", 10.0f));
        dataUnits.Add (new DataUnit ("AttackSpeed", -20.0f));
        dataUnits.Add (new DataUnit ("IsPoison", 1f));
        dataUnits.Add (new DataUnit ("WalkSpeed", 12f));
        dataUnits.Add (new DataUnit ("AttackSpeed", 5f));
        foreach (var unit in dataUnits) {
            // I want to mess with a separate variable in the Test class for each key
            swicth (unit.Key) {
                case "walkSpeed"
                    walkSpeed ​​+ = unit.Value;
                    break;
                case "attackSpeed"
                    attackSpeed ​​+ = unit.Value;
                    break;
                case "isPoison"
                    isPoison | = unit.Value>0f? true: false;
                    break;
                // More fields will be added
            }
        }
    }
    void Update () {
        // Reflect on character movement
    }
}
c#
  • Answer # 1

    In order to clarify what value eachfieldhas, I made a sample assuming the following cases.

    Assuming to create an action game

    I want each object to have the behavior when attacked


    First, define an interface to define multiple objects with the same behavior.

    public interface IHitable {
        void ReceiveDamage (int damage);
    }

    Next, define an object with that behavior.
    In the image,Bair.HitPointis the originalfieldA,Dog.HitPointis the originalfieldB,OldMan. IsDeadcorresponds to the originalfieldC.

    public class Bair: IHitable {
        private int HitPoint = 300;
        public void ReceiveDamage (int damage) {
            HitPoint-= damage/2;
        }
    }
    public class Dog: IHitable {
        private int HitPoint = 150;
        public void ReceiveDamage (int damage) {
            HitPoint-= damage;
        }
    }
    public class Oldman: IHitable {
        private bool IsDead;
        public void ReceiveDamage (int damage) {
            IsDead = damage>5;
        }
    }

    Finally, keepIHitableobjects in the list, and use polymorphism to call each element'sReceiveDamagemethod.
    You can now change the value held by each object member.

    By the way, the function called reflection is used to find the element corresponding to theDataUnitkey fromhitables. Perhaps, depending on the content and ingenuity, there is no need to use reflection.

    public class Test {
        Listhitables = new List();
        void TestFunc () {
            hitables.Add (new Bair ());
            hitables.Add (new Dog ());
            hitables.Add (new OldMan ());
            ListdataUnits = new List();
            dataUnits.Add (new DataUnit ("Bair", 20));
            dataUnits.Add (new DataUnit ("Dog", 1));
            dataUnits.Add (new DataUnit ("Oldman", 10));
            foreach (var unit in dataUnits) {
                var hitable = hitables.First (x =>x.GetType (). Name == unit.Key);
                hitable.ReceiveDamage (unit.Value);
            }
        }
    }

    In addition, in the posted code, I didn't understand the necessity of usingDataUnitsin the first place.
    I think the following way of writing looks good.

    public class Test {
        Listhitables = new List();
        void TestFunc () {
            var bair = new Bair ();
            bair.ReceiveDamage (20);
            var dog = new Dog ();
            dog.ReceiveDamage (1);
            var oldMan = new OldMan ();
            oldMan.ReceiveDamage (10);
            hitables.Add (new Bair ());
            hitables.Add (new Dog ());
            hitables.Add (new OldMan ());
        }
    }
    Things to consider for smartness Please clarify the difference between

    fieldA,fieldB,fieldC.
    It is probably better to have it in an array or collection.

    Please clarify the role ofDataUnits.
    If you don't need to define it, or if usingDataUnitsis rather complicated, you may want to consider another implementation.

    To increase the pattern

    Define a new class that implementsIHitable

    Add your own processing to theReceiveDamagemethod in that class

    Addan instance of the newly added class inhitables

    Now, when you enumeratehitables, the newly added instance method will be called.


    The posted code looks like this.
    The nameUpdateis abstract, but more specific names are likely to be difficult.

    public interface IAbility {
        void Update (float value);
    }
    public class Walk: IAbility {
        private float speed = 0f;
        public void Update (float value) {
            speed + = value;
        }
    }
    public class Attack: IAbility {
        private float speed = 0f;
        public void Update (float value) {
            speed + = value;
        }
    }
    public class Health: IAbility {
        private Condition condition = Condition.None;
        public void Update (float value) {
            condition = value>0f? Condition.Poison: Condition.None;
        }
    }
    public enum Condition {
        None,
        Poison,
        Burning,
        Palsy
    }
    public class Chara {
        Listabilities = new List();
        public Chara ()
        {
            abilities.Add (new Walk ());
            abilities.Add (new Attack ());
            abilities.Add (new Health ());
        }
        void TestFunc () {
            ListdataUnits = new List();
            // Save the table data from the database to dataUnits (the following generates data for debugging)
            dataUnits.Add (new DataUnit ("Walk", 10.0f));
            dataUnits.Add (new DataUnit ("Attack", -20.0f));
            dataUnits.Add (new DataUnit ("Health", 1f));
            dataUnits.Add (new DataUnit ("Walk", 12f));
            dataUnits.Add (new DataUnit ("Attack", 5f));
            foreach (var unit in dataUnits) {
                var ability = abilities.First (x =>x.GetType (). Name == unit.Key);
                ability.Update (unit.Value);
            }
        }
    }

Related articles