处理“一个,两个或没有”逻辑的正确方法是什么?

时间:2010-12-23 23:40:39

标签: php language-agnostic boolean-logic nested-if

我的逻辑情况最好被描述为试图赢得任务的两个“团队”。这项任务的结果可能是一个胜利者,一个平局(平局),或者没有胜利者(僵局)。

目前,我正在使用嵌套的if / else语句,如下所示:

// using PHP, but the concept seems language agnostic.
if ($team_a->win()) {
    if ($team_b->win()) {
        //  this is a draw
    } else {
        //  team_a is the winner
    }
} else {
    if ($team_b->win()) { 
        //  team_b is the winner
    } else {
        //  This is a stalemate, no winner.
    }
}

这似乎很像意大利面和重复。我可以使用更合乎逻辑的DRY模式吗?

10 个答案:

答案 0 :(得分:6)

另一种方式是win(a)&&赢(b)然后抽奖,否则如果赢(a),否则赢(b)。

或者:

if win(a) and win(b) then
   // Draw
else if win(a) then
   // a wins
else if win(b) then
   // b wins
else 
   // Stalemate

答案 1 :(得分:4)

我认为它不会比你现在做的好得多。

另一种方法是使用切换表达式:

switch (($team_a->win() << 1) + $team_b->win()) {
case 3:
    //  this is a draw
case 2:
    //  team_a is the winner
case 1:
    //  team_b is the winner
case 0:
    //  This is a stalemate, no winner.
}

然而,虽然它更干,但我认为这不会提高可读性。请注意,在某些语言而不是$team_x->win()中,您需要编写($team_x->win() ? 1 : 0)

答案 2 :(得分:3)

if($TeamA->win() && $TeamB->win()){
  // Tie
}else if($TeamA->win()){
  // Team A wins
}else if($TeamB->win()){
  // Team B wins
}else{
  // No winner
}

此外,根据你的win()方法的作用,在if...else之外检查一次可能更有效,所以它只运行一次检查:

$team_a = $TeamA->win();
$team_b = $TeamB->win();

if($team_a && $team_b){
  // Tie
}else if($team_a){
  // Team A wins
}else if($team_b){
  // Team B wins
}else{
  // No winner
}

答案 3 :(得分:2)

简化嵌套语句:

if($team_a->win() and $team_b->win())
{
  // Draw
}
elseif($team_a->win())
}
  // Team A Won
}
elseif($team_b->win())
}
  // Team B Won
}
else
{
  // No Winner
}

答案 4 :(得分:1)

这是@Mark Byers版本的扩展版本,旨在使其背后的逻辑更加清晰。

$result_code = 0;
if ($team_a->win()) $result_code += 1;
if ($team_b->win()) $result_code += 2;
switch ($result_code) {
   case 0:
      //stalemate
   case 1:
      //a wins
   case 2:
      //b wins
   case 3:
      //draw
}

这是一个非常好的程序,这个数字不会在任何组合中得出相同的结果,我想你将来会有很多场合使用它。它与* nix权限中使用的逻辑相同,可以使用&lt; 2个操作数:如果它们是3个,你可以使用4,2和1等等。

在这种特殊情况下,它也加快了处理速度,因为你只需要调用一次团队对象的方法。

答案 5 :(得分:1)

当这种类型的逻辑被封装在一个方法中时,早期返回可能比{} else阻塞更可读:

function game_end($a,$b) {
    if ($team_a->win() && $team_b->win()) {
            //  this is a draw
            return;
    } 

    if ($team_a->win()) {
            //  team_a is the winner
            return ;
    }

    if ($team_b->win()) {
            //  team_b is the winner
            return ;
    }

    //  This is a stalemate, no winner.

}

答案 6 :(得分:0)

你不能使用更直接的陈述......

类似

IF(a AND b) THEN {a,b}
ELSE If (a AND NOT(b)) THEN {a}
ELSE If (not(a) AND NOT(b)) THEN { }
ELSE {b}

与其他一些帖子相比,这是非常易读但不是最简洁的。

答案 7 :(得分:0)

如果您要分成两组,请考虑:

if (win(a) != win(b)) {
    // common code when there's a winner, regardless of who
    if (win(a)) {
        // code specific to a winning
    } else {
        // code specific to b winning
    }
} else {
    // common code for a non-result
    if (win(a)) {
        // code specific to a draw
    } else {
        // code specific to a stalemate
    }
}

如果你处于两个位置之一中有一些共同代码的最佳位置,可能会有用,但是抽象到一个函数并且从四个块中的两个块调用它是不值得的,或者是不可能的。 if/else ifswitch/case答案。

答案 8 :(得分:0)

就像我在评论中所说,我认为胜利条件及其决定是在错误的地方。 (例如快速电子代码)有什么问题:

if ($team_a->score() > $team_b->score()) return 'Team A wins!';
else if ($team_a->score() < $team_b->score()) return 'Team B wins!';
else return 'It's a tie!';

(语法可能有误,但你明白了)

重构比尝试自己创建问题的解决方案更好。

答案 9 :(得分:0)

寻找干燥模式的问题在这里是错误的,因为问题既不复杂也不足以保证重构/简化,并且其圈复杂性太低而无法担心 spaghettization

这是一个算法问题,准确的布尔代数...... 和一个非常简单的启动。您必须进行3次比较,至少4个分支做出决定。

IF (A ^ B) -> draw
ELSE (!A ^ !B) -> no win
ELSE A -> a wins
ELSE -> b wins

用更少的东西做逻辑是不可能的。这里唯一的冗余是$team_b->win()的重新计算(简单地计算两个团队的胜利,并在if语句之前将它们放在本地变量中)。