Home > database >  Is there any way to make a switch statement out of this mess of if else if?
Is there any way to make a switch statement out of this mess of if else if?

Time:10-29

Is there an easier way to do this without bringing in a bunch of mathematics? Perhaps maybe a switch statement?

            if (myChoice == "Rock" && compChoice == "Scissors")
            {
                winner = "player";
                win  ;
            }

            else if (myChoice == "Rock" && compChoice == "Lizard")
            {
                winner = "player";
                win  ;
            }

            else if (myChoice == "Paper" && compChoice == "Rock")
            {
                winner = "player";
                win  ;
            }

            else if (myChoice == "Paper" && compChoice == "Spock")
            {
                winner = "player";
                win  ;
            }

            else if (myChoice == "Scissors" && compChoice == "Paper")
            {
                winner = "player";
                win  ;
            }

            else if (myChoice == "Scissors" && compChoice == "Lizard")
            {
                winner = "player";
                win  ;
            }

            else if (myChoice == "Lizard" && compChoice == "Spock")
            {
                winner = "player";
                win  ;
            }

            else if (myChoice == "Lizard" && compChoice == "Paper")
            {
                winner = "player";
                win  ;
            }

            else if (myChoice == "Spock" && compChoice == "Scissors")
            {
                winner = "player";
                win  ;
            }

            else if (myChoice == "Spock" && compChoice == "Rock")
            {
                winner = "player";
                win  ;
            }

            else if (compChoice == "Rock" && myChoice == "Scissors")
            {
                winner = "computer";
                lose  ;
            }

            else if (compChoice == "Rock" && myChoice == "Lizard")
            {
                winner = "computer";
                lose  ;
            }

            else if (compChoice == "Paper" && myChoice == "Rock")
            {
                winner = "computer";
                lose  ;
            }

            else if (compChoice == "Paper" && myChoice == "Spock")
            {
                winner = "computer";
                lose  ;
            }

            else if (compChoice == "Scissors" && myChoice == "Paper")
            {
                winner = "computer";
                lose  ;
            }

            else if (compChoice == "Scissors" && myChoice == "Lizard")
            {
                winner = "computer";
                lose  ;
            }

            else if (compChoice == "Lizard" && myChoice == "Spock")
            {
                winner = "computer";
                lose  ;
            }

            else if (compChoice == "Lizard" && myChoice == "Paper")
            {
                winner = "computer";
                lose  ;
            }

            else if (compChoice == "Spock" && myChoice == "Scissors")
            {
                winner = "computer";
                lose  ;
            }

            else if (compChoice == "Spock" && myChoice == "Rock")
            {
                winner = "computer";
                lose  ;
            }

            else
            {
                winner = "none";
                tie  ;
            }

I played around with this for a little while but looking for an easier way to show some friends that are learning c#. I'm quite the beginner myself so I wasn't able to offer anymore assistance. I'm hoping that someone on here can point us in the right direction. Thanks in advance for any advice you can offer.

CodePudding user response:

I'd personally get rid of as many of those strings as possible. Here's what you could do with a couple enums and a supporting class to play a round of the game.

public enum Choice
{
    Rock, Paper, Scissors, Spock, Lizard
}

public enum Result
{
    Win, Lose, Draw
}

public static class Roshambo
{
    // This is a lookup table of the choice against what it beats.
    private static readonly Dictionary<Choice, List<Choice>> Any = new()
    {
        {Choice.Rock, new() {Choice.Scissors, Choice.Lizard}},
        {Choice.Paper, new() {Choice.Rock, Choice.Spock}},
        {Choice.Scissors, new() {Choice.Paper, Choice.Lizard}},
        {Choice.Lizard, new() {Choice.Spock, Choice.Paper}},
        {Choice.Spock, new() {Choice.Scissors, Choice.Rock}}
    };
    public static Result Play(Choice one, Choice theOther)
    {
        if (one == theOther) return Result.Draw;
        return Any[one].Contains(theOther) 
            ? Result.Win 
            : Result.Lose;
    }
}
public static void Main(string[] args)
{
    var result = Roshambo.Play(Choice.Scissors, Choice.Rock);
    // Here you could switch over the result
    Console.WriteLine(result); // Lose
}

CodePudding user response:

This is a good candidate for a switch expression, if your compiler is new enough to support it:

winner = myChoice switch
{
     "Rock" => compChoice switch
     {
          "Rock" => "none",
          "Scissors" or "Lizard" => "player",
          "Paper" or "Spock" => "computer"
     },
     "Scissors" => compChoice switch
     {
          "Scissors" => "none",
          "Paper" or "Lizard" => "player",
          "Rock" or "Spock" => "computer"
     }
     // and so on
}

Naturally this also works with proper enum variables.

But this is still redundant, as you have to have anti-symmetric entries. We can take advantage of that:

bool beats(string first, string second)
   => first switch
      {
          "Rock" => second is "Scissors" or "Lizard",
          "Scissors" => second is "Paper" or "Lizard",
          "Paper" => second is "Rock" or "Spock",
          "Lizard" => second is "Paper" or "Spock",
          "Spock" => second is "Rock" or "Scissors"
      };

 bool playerWins = beats(playerChoice, compChoice);
 bool computerWins = beats(compChoice, playerChoice);
 switch ((playerWins, computerWins)) {
     case (true, false):
         winner = "player";
         wins  ;
         break;
     case (false, true):
         winner = "computer";
         loss  ;
         break;
     case (false, false):
         winner = "none";
         draw  ;
         break;
     case (true, true):
         MessageBox.Show("Problem with the rules!");
         break;
 }

This is competitive with a lookup table for code length and probably more readable. And it checks the consistency of the rules, you can't accidentally make player "Rock" beat computer "Paper" at the same time that player "Paper" beats computer "Rock".

CodePudding user response:

If we have all states as

static List<string> states = new List<string> {
  "Scissors", "Paper", "Rock", "Lizzard", "Spock"
};

the rules will be simple:

A wins B if and only if either indexB - indexB == 1 or indexB - indexA == 2.

E.g. Rock wins Scissors and Lizzard

Note, however, that we should compute circular differencies (-1 ~ 4, -2 ~ 3, -3 ~ -2 etc.), e.g. Spock wins Scissors; me can do it with a help of modulo arithmetics:

private static bool FirstWins(string first, string second) {
  int difference = (states.IndexOf(first) - states.IndexOf(second)   states.Count) 
     % states.Count;

  return difference == 2 || difference == states.Count - 1; 
}  

Finally

static string Winner(string user, string computer) =>
    FirstWins(user, computer) ? "User"
  : FirstWins(computer, user) ? "Computer"
  : "Draw";
  • Related