8

1 つのメソッド呼び出しのみが異なるクラスにこれら 2 つのメソッドがあります。明らかに、これは非常に乾燥していません。特に、両方が同じ式を使用しているためです。

int PlayerCharacter::getAttack() {
    int attack;
    attack = 1 + this->level;
    for(int i = 0; i < this->current_equipment; i++) {
        attack += this->equipment[i].getAttack();
    }
    attack *= sqrt(this->level);
    return attack;
}
int PlayerCharacter::getDefense() {
    int defense;
    defense = 1 + this->level;
    for(int i = 0; i < this->current_equipment; i++) {
        defense += this->equipment[i].getDefense();
    }
    defense *= sqrt(this->level);
    return defense;
}

これを C++ で整理するにはどうすればよいですか?

4

7 に答える 7

18

簡単な方法の 1 つは、すべての機器の属性を列挙型でインデックス付けされた配列で表すことです。

enum Attributes {
  Attack, 
  Defense,
  AttributeMAX
};

class Equipment {
  std::vector<int> attributes;

  Equipment(int attack, int defense): attributes(AttributeMAX)
  {
    attributes[ATTACK] = attack;
    attributes[DEFENSE] = defense;
  }

};

次に、関数を次のように変更します

int PlayerCharacter::getAttribute(int& value, Attribute attribute) {
    value = 1 + this->level;
    for(int i = 0; i <= current_equipment; i++) {
        value += this->equipment[i].attributes[attribute];
    }
    value *= sqrt(this->level);
    return value;
}

そして、あなたはそれをそのように呼ぶことができます

  player.getAttribute(player.attack, Attack);
于 2010-04-19T18:51:35.057 に答える
12

私の意見では、あなたが持っているものは問題ありません.1つの機能で両方を表す場合よりも、攻撃/防御を微調整できるからです. ゲームのテストを開始したら、攻撃と防御の公式のバランスを取り始めます。そのため、それらに個別の関数を用意しても問題ありません。

DRY [自分を繰り返さないでください] の全体的な概念は、[願わくば] あなたのコードが巨大なコピー & ペーストの大騒ぎになるのを防ぐことです。あなたの状況では、防御/攻撃の式は時間の経過とともに変化します[たとえば、キャラクターにバフ/状態異常がある場合はどうなりますか? 特定の状態異常により、防御力が半分になり、攻撃力が 2 増加する場合があります (ベルセルク、FF 参照、へー)]

于 2010-04-19T18:43:55.113 に答える
6

厳密なリファクタリングの観点から、これを行うことができます:

int PlayerCharacter::getDefense() {
    return getAttribute(&EquipmentClass::getDefense);
}

int PlayerCharacter::getOffense() {
    return getAttribute(&EquipmentClass::getOffense);
}

int PlayerCharacter::getAttribute(int (EquipmentClass::*attributeFun)()) {
    int attribute = 0;
    attribute= 1 + this->level;
    for(int i = 0; i <= current_equipment; i++) {
        attribute += this->equipment[i].*attributeFun();
    }
    attribute *= sqrt(this->level);
    return attribute;
}
于 2010-04-19T18:53:28.610 に答える
5

まあ、少なくともsqrt(this.level);別の関数として抽出することを検討しますgetLevelModifier()

defense = 1 + this.level;

attack = 1 + this.level;

になり得る

defense = getBaseDefense();

attack= getBaseAttack();

これにより柔軟性が向上するだけでなく、関数が自動ドキュメント化されます。

于 2010-04-19T18:51:51.777 に答える
3

アプリケーション内の他のコードに応じて、価値がある場合とそうでない場合がありますが、OOP アプローチは、防御と攻撃の値をプレーンではなくクラスのオブジェクトにしますint。次に、必要に応じて各サブクラスによって定義された仮想 getEquipmentRate() メソッドを呼び出す get() メソッドを持つ共通の基本クラスからそれらを派生させることができます。

于 2010-04-19T19:22:59.207 に答える
2

ltzWartyの回答とは別に、読みやすくするためにループを関数にリファクタリングすることをお勧めします。

int PlayerCharacter::getEquipmentAttack() {
    int attack = 0;
    for(int i = 0; i <= current_equipment; i++) {
        attack += this.equipment[i].getAttack();
    }
    return attack;
}
int PlayerCharacter::getAttack() {
    int attack = 1 + this->level;
    attack += getEquipmentAttack();
    attack *= sqrt(this->level);
    return attack;
}

また、ローカル変数を宣言するときは、すぐに初期化するattack必要があります。

于 2010-04-19T19:06:41.387 に答える
2

IMO、ItzWarty は妥当な点を指摘しています。コードをそのままにしておくこともできます。ただし、それを変更することは良いことだと判断したと仮定すると、次のようにすることができます。

class equipment { 
public:
    int getAttack();
    int getDefense();
};

int PlayerCharacter::getBattleFactor(int (equipment::*get)()) { 
    int factor = level + 1;
    for (int i=0; i<current_equipment; ++i)
        factor += equipment[i].*get();
    return factor * sqrt(level + 1);
}

これを次のように呼び出します。

int attack = my_player.getBattleFactor(&equipment::getAttack);

また:

int defense = my_player.GetBattleFactor(&equipment::getDefense);

編集:

もう 1 つの明白な可能性は、どの 1 つの装備も防御用または攻撃用にしか使用できないと布告することです。この場合、物事はさらに単純になり、関数が本当に必要かどうかさえ疑わしいかもしれません。

class PlayerCharacter {
    std::vector<equipment> d_equip;
    std::vector<equipment> o_equip;

// ...

int d=level+1+std::accumulate(d_equip.begin(), d_equip.end(), 0)*sqrt(level+1);

int o=level+1+std::accumulate(o_equip.begin(), o_equip.end(), 0)*sqrt(level+1);
于 2010-04-19T18:59:07.737 に答える