2010-09-01 86 views
2

什么是对付这样的事情最好的办法:处理大量的if-else语句,转

if(key==Space) 
{ 
    switch(weapon) 
    { 
     case GUN: 
      p->shotGun(); 
      break; 
     case BOW: 
      p->shotBow(); 
      break; 
    } 
} 
else if(key==Enter) 
{ 
    //... 
} 
else if(key==Up) 
{ 
    //... 
} 
+0

对我来说似乎没问题......键是什么类型? – 2010-09-01 12:01:39

回答

5

我倾向于使用地图类型的表达式:话又说回来

unordered_map<KEY_PRESS,ICommand> myCommands; 
unordered_map<KEY_PRESS,ICommand>::const_iterator currentCommand = myCommands.find(key); 
if(currendCommand != myCommands.end()){ 
    currentCommand->performAction(weapon); 
} 

,如果你制造的武器为对象,而不是标志,你可以逃脱的重载函数模式。

+0

+1用于识别可能使用的命令模式:) – Wix 2010-09-01 12:13:00

1

如何嵌套switch语句的水平?为了更好的可读性,我还会重构二级开关来分离函数。

10

拆分一个维度分为两个:

switch (key) 
{ 
    case Space: 
    ProcessSpaceCmd(); 
    break; 

    case Enter: 
    ProcessEnterCmd(); 
    break; 

    case Up: 
    ProcessUpCmd(); 
    break; 
} 

看到什么尺寸较长,[key][weapon],并以最短的外部开关。

+2

如果开发人员不小心,这可能导致意大利面条仓库,但考虑到OP的需求,这是明智的。 – 2010-09-01 12:08:09

+1

没关系,意大利面条仓库有很好的食物。 :-) – 2010-09-01 12:34:23

2

或者,如果你真的想摆脱if-elses,你可以使用某些形式的关键代码和方法之间的映射。具体取决于该键码是连续它可以被映射或者干脆键码索引像一个数组:

KeyMethods[key]();

+0

提醒我在11个小时内回来,并注意这一点。 :) – sarnold 2010-09-01 12:10:55

9

你可能要考虑使用Command和/或Strategy模式。命令模式似乎非常适合外部的if/else,而策略模式似乎非常适合内部开关。

cmd = Command->GetCommand(key); 
    cmd->Perform(); 

,并执行与所述空格键

weapon = PlayState->GetCurrentWeapon(); 
    weapon->Fire(); 

注意后者依赖于一些全局缓存/状态,以保持当前的武器(策略)相关联的命令。

这样做的效果是将if/else逻辑移到确定当前命令的工厂方法中。选择哪个命令选择if/else分支之一。将当前武器存储在游戏状态中可以让你轻松选择要使用哪种武器的Fire方法,从而将选择武器的开关“逻辑”移至武器选择逻辑并完全“消失”。每种武器策略都知道如何执行自己的“火力”逻辑。

+0

它可以很容易地适应,但不需要任何全球性的。 – 2010-09-01 12:08:13

0

我建议至少将每个if的内容分成它自己的函数。

if(key == Space) 
    FureCurrentWeapon(); 
else if(key == Enter) 
    Activate(); 
else if(key == Up) 
    WalkForwards(); 

我以前用过的另一种方法是创建一个基类,它可以由每个接收键盘输入的类派生。保留从它派生的类的列表,然后在每次接收输入时遍历该列表,传递按键并让它们在需要时处理它。

3

既然是C++,你可能想要利用它的面向对象方面的优势。为IProjectileWeapon等武器制作界面,并创建一个实现该界面的弓和枪类。然后当你调用Shoot()方法时,它将使用正确的行为。这将摆脱武器的转换声明。让Character类拥有武器作为成员并且使用UseWeapon()作为方法可能会更好。所以UseWeapon()方法会调用武器的Shoot()方法。

对于移动,将移动命令添加到Character类并传递角色应移动的方向。

2

另一种可能性:

class Weapon { 
    public: 
    abstract void shoot(); 
} 

class Gun: public Weapon { 
    public: 
    void shoot(); 
} 

class Bow: public Weapon { 
    public: 
    void shoot(); 
} 

if(key==Space) 
{ 
    weapon.shoot(); 
} 
else if(key==Enter) 
{ 
    //... 
} 
else if(key==Up) 
{ 
    //... 
} 

至于if报表长长的火车,这很好。一个switch声明也可以用IFF来处理整数。但是在每个人中都有break声明可能会分散注意力,忘记它会是灾难性的。如果您需要在内部循环中加速性能关键代码,则更重要。 (else if依次评估每一个,直到找到一个匹配为止switch直接跳到正确的选项。)

+0

您确定“抽象”关键字吗?也许应该是“虚拟”而不是?但你的观点很好。使用多态是绝对比使用“开关”更好的方法... – ThR37 2010-09-01 12:17:13

0

使你的武器类变得虚拟。