0

我有一个 IF 语句,我想将其转换为一个 Switch 语句......但它有 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!");

同一行中的两个案例

使用解决:

#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语句使用单个变量。但是,在某些情况下,您可以进行转换。例如,如果您有两个变量,aand 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

由于switch对单个变量进行操作,因此您必须能够以某种方式将多个输入组合成一个值。给定 ASCII 字符“R”、“P”和“S”的数值,将这两个字符加在一起将为每个配对提供唯一的总和。但是,生成的代码可能比等效的if树更难阅读。一般来说,这通常不是一个好的选择,因为当添加新的输入选项并且您的“组合”操作(例如唯一总和)的基本假设不再成立时,您的代码将很容易中断。 switch随着可能输入值数量的增加,它也会变得笨拙。由于您需要一个case适合所有可能的组合,因此您的switch当与少数输入选项一起使用时,会变得很大并且难以维护。

一个switch块实际上会导致比if在这种特殊情况下使用更多的代码。使用if使您能够一次处理多个案例。例如,您不需要检查平局的三个不同版本的代码。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 回答
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

过于聪明的解决方案:

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 回答