5

私は、タスクを勝ち取ろうとする 2 つの「チーム」として最もよく説明される論理的な状況を持っています。このタスクの結果は、1 人の勝者、同点 (引き分け)、または勝者なし (膠着状態) のいずれかです。

現在、ネストされた 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 なパターンはありますか?

4

10 に答える 10

6

もう 1 つの方法は、win(a) && win(b) の場合は引き分け、そうでない場合は win(a)、それ以外の場合は win(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
于 2010-12-23T23:45:02.013 に答える
4

あなたが現在行っていることよりもはるかに良いことはできないと思います。

1 つの代替方法は、switch 式を使用することです。

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.
}

ただし、より DRY ですが、これにより読みやすさが向上するとは思いません。一部の言語では、代わり$team_x->win()($team_x->win() ? 1 : 0).

于 2010-12-23T23:44:26.297 に答える
3
if($TeamA->win() && $TeamB->win()){
  // Tie
}else if($TeamA->win()){
  // Team A wins
}else if($TeamB->win()){
  // Team B wins
}else{
  // No winner
}

if...elseまた、 win() メソッドが何をするかによっては、チェックを 1 回だけ実行するように、外側で 1 回チェックする方が効率的な場合があります。

$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
}
于 2010-12-23T23:47:22.010 に答える
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
}
于 2010-12-23T23:46:25.797 に答える
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
}

これは非常に優れた手順です。これは、どの組み合わせでも同じ結果にならない数字の 1 つです。将来、この手順を使用する機会がたくさんあると思います。これは、*nix パーミッションで使用されるのと同じロジックであり、2 つ未満のオペランドでも機能します。オペランドが 3 つの場合は、4、2、1 などを使用できます。

この特定のケースでは、チーム オブジェクトのメソッドを 1 回呼び出すだけなので、処理も高速化されます。

于 2010-12-24T01:18:08.070 に答える
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.

}
于 2010-12-24T01:58:04.007 に答える
0

コメントで言ったように、勝利条件とその決定は間違った場所にあると思います。何が問題なのか (クイック e コードの例):

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!';

(構文は間違っているかもしれませんが、アイデアは得られます)

自分で作成した問題の解決策を考えようとするよりも、リファクタリングする方がよいでしょう。

于 2010-12-28T15:51:24.707 に答える
0

2 人ずつ 2 つのグループに分かれる場合は、次の点を考慮してください。

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
    }
}

2 つの位置のいずれかに共通のコードがあるスイート スポットにいる場合に役立つ可能性がありますが、関数に抽象化して and の 4 つのブロックのうちの 2 つから呼び出すことは価値がないか、不可能if/else ifですswitch/case。 .

于 2010-12-24T02:47:01.743 に答える
0

問題はリファクタリング/単純化を正当化するほど複雑ではなく、循環的複雑度が低すぎてスパゲッティゼーションを心配できないため、DRY パターンを探すという質問はここでは間違っています。

これはアルゴリズムの問​​題であり、正確にはブール代数です...そして起動するのは非常に簡単です。決定を下すには、少なくとも 3 つの比較と 4 つの分岐を行う必要があります。

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

それ以下でロジックを実行することはできません。ここでの唯一の冗長性は、$team_b->win()(単純に両方のチームの勝利を計算し、if ステートメントの前にローカル変数に入れる) の再計算です。

于 2011-02-02T22:54:24.500 に答える
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}

他のいくつかの投稿とは対照的に、これは非常に読みやすいですが、最も簡潔ではありません。

于 2010-12-23T23:43:38.603 に答える