C++ 如何使这个C++;代码更干?

C++ 如何使这个C++;代码更干?,c++,dry,code-cleanup,C++,Dry,Code Cleanup,我在一个类上有这两个方法,它们只在一个方法调用上有所不同。显然,这是非常不干燥的,尤其是因为两者使用相同的配方 int PlayerCharacter::getAttack() { int attack; attack = 1 + this->level; for(int i = 0; i < this->current_equipment; i++) { attack += this->equipment[i].getAttack

我在一个类上有这两个方法,它们只在一个方法调用上有所不同。显然,这是非常不干燥的,尤其是因为两者使用相同的配方

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;
}
int PlayerCharacter::getAttack(){
智力攻击;
攻击=1+这个->等级;
对于(int i=0;icurrent_设备;i++){
攻击+=此->设备[i].getAttack();
}
攻击*=sqrt(此->级别);
回击;
}
int PlayerCharacter::getDefense(){
智力防御;
防御=1+这个->等级;
对于(int i=0;icurrent_设备;i++){
防御+=此->设备[i].getDefense();
}
防御*=sqrt(本->级别);
回击防守;
}

<>我如何在C++中整理这个?

,在我看来,你有什么好的,因为它可以让你调整攻击/防御比你用一个函数来表示攻击和防御更有效。一旦你开始测试你的游戏,你将开始平衡攻击/防御公式,所以为它们设置单独的函数是很好的


DRY[不要重复你自己]的整个概念[希望]是为了防止你的代码成为一个巨大的复制粘贴盛会。在你的情况下,防御/攻击公式会随着时间的推移而改变[例如,如果角色有增益/状态疾病怎么办?一个特定的状态疾病可能会将防御减半,而攻击增加2(狂暴,FF参考,呵呵)]

一个简单的方法是在一个数组中表示一件装备的所有属性,由枚举索引

enum Attributes {
  Attack, 
  Defense,
  AttributeMAX
};

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

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

};

嗯,我至少应该考虑提取<代码> SqRT(这个.level);

作为一个单独的函数,名为
getLevelModifier()

可能是

defense = getBaseDefense();

attack= getBaseAttack();

这不仅增加了灵活性,还自动记录了您的功能。

从严格的重构角度来看,您可以这样做:

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;
}
int PlayerCharacter::getDefense(){
返回getAttribute(&EquipmentClass::getDefense);
}
int PlayerCharacter::GetOffices(){
返回getAttribute(&EquipmentClass::getAttribute);
}
int PlayerCharacter::getAttribute(int(设备类::*attributeFun)(){
int属性=0;
属性=1+此->级别;
对于(int i=0;i设备[i].*attributeFun();
}
属性*=sqrt(此->级别);
返回属性;
}

依我看,伊兹瓦蒂提出了一个合理的观点——你可能想不去管代码。假设你认为更改代码是件好事,你可以这样做:

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);
}
或:

编辑:

另一个明显的可能性是命令任何一件设备只能是防御性的或进攻性的。在这种情况下,事情变得更简单,甚至可能会怀疑你是否真的需要一个功能:

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);
class PlayerCharacter{
std::向量d_设备;
标准:向量o_设备;
// ...
int d=等级+1+std::累加(d_装备开始(),d_装备结束(),0)*sqrt(等级+1);
int o=等级+1+std::累加(装备开始(),装备结束(),0)*sqrt(等级+1);
除了您的答案之外,我建议您将循环重构为一个函数,以提高可读性:

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;
}
int PlayerCharacter::getEquipmentAttack(){
int攻击=0;
对于(int i=0;i级;
攻击+=获取设备攻击();
攻击*=sqrt(此->级别);
回击;
}

另外,当您声明局部变量
attack
时,您应该。

取决于应用程序中的其他代码,它可能值得,也可能不值得,但OOP方法将使防御和攻击值对象成为类的对象,而不是普通的
int
。然后您可以从具有get()的公共基类派生它们方法,该方法根据需要调用每个子类定义的虚拟getEquipmentRate()方法。

此方法。
给我们发一些真实的代码。:)GMan说的也是:<代码>攻击<代码> >代码>防御>代码>全局变量,还是你忽略了它们的定义?FAEPALM——这是我在数月的其他语言之后的第一个真正的C++:P.可能更糟,我可以做到“代码>自我。< /代码>,因为大部分是Python。@ SBI:而另一个问题是白痴,那就是复制/粘贴器。ror@sbi:我同意,不要重复你自己是我最好的猜测。虽然(理论上)有一些方法可以让你所做的事情(使用一些函数指针)的基础数学变得枯燥乏味,但从长远来看,你很可能会为每种方法编写不同的包装器方法,就像@ItzWarty所建议的那样您开始以不同的方式篡改这两个值。您也想到了这一个,但却懒得把它说出来。=)这是一个很好的解决方案,因为它不会混淆代码的意图。但是,它确实会混淆用法。但是,通过创建两个名为getAttack和GetDefense的包装例程,可以很容易地解决这个问题,这两个例程依次调用例程。(编辑),但我会说player.getAttribute(player.attack,attack)这本身就非常清楚。+1。在你在ctor中分配属性之前,你需要初始化属性的数量。
属性。
属性的数量。
属性的数量当然是在ctor中。谢谢,出于某种原因,我认为如果你试图将向量索引到范围之外,向量会动态扩展。+1表示
战斗因子
。这听起来很棒,让我们想玩它(不管是什么)。
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);
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);
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;
}