0

Switch ステートメントに変換したい IF ステートメントがありますが、2 つの変数があります。Cでそれを行うことは可能ですか?

これはじゃんけんゲームです。

(Rはじゃんけん、Pは紙、Sははさみ)

     char play1, play2;

     printf("\nPlayer 1 - Enter your Play: ");
     scanf ("%c", &play1);
     printf("\nPlayer 2 - Enter your Play: ");
     scanf (" %c", &play2); 


     if (play1 == 'R' && play2 == 'P') {
       printf ("Paper wins!"); }
      else if (play1 == 'R' && play2 == 'S') {
        printf ("Rock wins!");}
      else if (play1 == 'R' && play2 == 'R) {
        printf ("Draw!");}

他のオプションについてもこれを行う必要があるため、switch を使用する方がよいでしょう。

4

7 に答える 7

9
#include <stdio.h>

#define SWITCH(a, b) char _a = a; char _b = b; if (0)
#define CASE(a, b) } else if ((a == _a) && (b == _b)) {

int main(void)
{
    char play1, play2;

    printf("\nPlayer 1 - Enter your Play:");
    scanf ("%c", &play1);
    getchar();
    printf("\nPlayer 2 - Enter your Play:");
    scanf ("%c", &play2);
    getchar();

    SWITCH(play1, play2) {
        CASE('R','P') printf ("Paper wins!");
        CASE('R','S') printf ("Rock wins!");
        CASE('R','R') printf ("Draw!");
    }
    return 0;
}

冗談です:P

編集: ":" の大文字と小文字のサポート

#define PASTE(a, b) a##b
#define LABEL(a, b) PASTE(a, b)
#define SWITCH(a, b) char _a = a; char _b = b; if (0)
#define CASE(a, b) } else if ((a == _a) && (b == _b)) { LABEL(LBL, __LINE__)

ただし、次のものでは機能しません:

CASE('R','R'): printf ("Draw a!"); CASE('S','R'): printf ("Draw!");

同じラインの 2 つのケース

以下を使用して解決:

#define SWITCH(a, b) char _a = a; char _b = b; if (0)
#define CASE(a, b) } else if ((a == _a) && (b == _b)) {switch(1) case 1

誰もそれを使用しないことを願っています:)

于 2013-01-04T17:38:19.907 に答える
6

一般に、答えは「いいえ」です。switchステートメントは単一の変数で機能します。ただし、場合によっては変換を行うことができます。たとえば、2つの変数とがaありb、ここaで0、1、または2の場合があり、bそれが0, 1, 2, or 3の場合は、次のように切り替えることができます。

switch (a*10+b) {
    case  0: break; // a == 0, b == 0
    case 10: break; // a == 1, b == 0
    case 20: break; // a == 2, b == 0
    case  1: break; // a == 0, b == 1
    case 11: break; // a == 1, b == 1
    case 21: break; // a == 2, b == 1
    case  2: break; // a == 0, b == 2
    case 12: break; // a == 1, b == 2
    case 22: break; // a == 2, b == 2
    case  3: break; // a == 0, b == 3
    case 13: break; // a == 1, b == 3
    case 23: break; // a == 2, b == 3
}
于 2013-01-04T15:57:54.577 に答える
2
#include <stdio.h>
#include <stdlib.h>

#define PAIR(X,Y) (X<<8)|Y

int main()
{
    char play1, play2;

    printf("\nPlayer 1 - Enter your Play: ");
    scanf ("%c", &play1);
    printf("\nPlayer 2 - Enter your play: ");
    scanf (" %c", &play2); 

    switch (PAIR(play1, play2)) {
        case PAIR('R','P'):
            printf ("Paper wins!\n");
            break;
        case PAIR('R','S'):
            printf ("Rock wins!\n");
            break;
        case PAIR('R','R'):
            printf ("Draw!\n");
            break;
        default: //any thing else
            printf ("Default!\n");
            break;
    }
}
于 2013-01-04T16:25:13.970 に答える
1

これを簡潔に実現するには、複数文字の文字定数をお勧めします。

switch ((play1 << 8) + play2) {

  case 'RP':

    printf ("Paper wins!");
    break;

  case 'RS':

    printf ("Rock wins!");
    break;

  case 'RR':

    printf ("Draw!");
    break;
 }
于 2013-01-04T21:43:02.080 に答える
0

あまりにも賢い半分の解決策:

enum Play { Rock = 0, Paper = 1, Scissors = 2 };
enum Outcome { Tie = 0, P1Win = 1, P2Win = 2 };

enum Play parseMove(char input) {
    switch (input) {
        case 'R': return Rock;
        case 'P': return Paper;
        case 'S': return Scissors;
        default: /* invalid input */;
    }
}

enum Outcome gameResult(enum Play p1, enum Play p2) {
    return (3 + p1 - p2)%3;
}

...

switch(gameResult(parseMove(play1), parseMove(play2))) {
    case Tie: printf("Tie!\n");
    case P1Win: printf("Player 1 wins!\n");
    case P2Win: printf("Player 2 wins!\n");
}
于 2013-01-04T17:49:31.793 に答える
0

switch次のように、式ごとにステートメントをネストできます。

switch(a)
{
  case 'A':
    switch(b)
    {
      case 0: // do something with A0
        break;
      case 1: // do something with A1
        break;
      ...
    }
    break;

  case 'B':
    switch(b)
    {
      case 0: // do something with B0
        break;
      ...
    }
    break;
  ...
}

ご覧のとおり、これはすぐに非常に醜くなる可能性があります。値の組み合わせに基づいて分岐する必要がある場合は、おそらく現在の構造を維持した方がよいでしょう。

于 2013-01-04T16:14:28.357 に答える
0

単一の変数で動作するためswitch、複数の入力を何らかの方法で単一の値に結合できる必要があります。ASCII 文字 'R'、'P'、および 'S' の数値が与えられた場合、2 つの文字を合計すると、ペアごとに一意の合計が得られます。ifただし、結果のコードは、同等のツリーよりも読みにくい可能性があります。通常、これは適切なオプションではありません。新しい入力オプションが追加され、"組み合わせ" 演算 (一意の合計など) の基礎となる仮定が保持されなくなると、コードが非常に簡単に壊れてしまうからです。 switchまた、可能な入力値の数が増えると扱いにくくなります。case可能なすべての組み合わせが必要なので、switchほんの一握りの入力オプション以外で使用すると、大きくなり、保守が困難になります。

ブロックは実際には、この特定のケースで使用するよりswitchも多くのコードになります。ifを使用ifすると、一度に複数のケースを処理できます。たとえば、同点をチェックするコードの 3 つの個別のバージョンは必要ありません。switchまたはの代わりに表を使用して回答を検索することもできますif。これらのアプローチを組み合わせた例を次に示します。

// Table of outcomes.  The option in the second
// column wins over the option in the first column.
char matchup[3][2] = {
  {'P', 'S'}, // paper is cut and destroyed
  {'S', 'R'}, // scissors are smashed and destroyed
  {'R', 'P'}, // rock is ... covered up?
};

void announce_winner(char player1, char player2)
{
  int i;

  if (player1 == player2) {
    printf("Draw\n");
    return;
  }

  for (i=0; i<3; ++i) {
    if (player1 == matchup[i][0])
      printf("%c wins\n", (player2 == matchup[i][1]) ? player2 : player1);
  }
}

テーブル アプローチの大きな利点は、コードがデータから分離されていることです。ゲームのルールが変更された場合、または誰かがゲームを学んでいて、どの状況で誰が勝つかを知りたい場合、多くのコードを掘り下げるよりも、テーブルの方がはるかにユーザーフレンドリーになります。ブロックは基本的switchに、ルックアップ テーブルと処理コードがすべて混ざり合ったものであり、複雑なケースの場合、見苦しくなります。

于 2013-01-04T22:35:30.990 に答える