【问题标题】:Rock, Paper, Scissors in C#C#中的石头、纸、剪刀
【发布时间】:2020-11-22 14:03:58
【问题描述】:

我正在用 C# 制作石头、剪纸、剪刀游戏,目前在有人输入不是 R、S 或 P 的输入时尝试显示消息时遇到问题。例如,我正在尝试获取默认值在 switch 语句中工作,但我没有运气。这是我目前拥有的。如果我有任何其他问题,请告诉我。

using System;

namespace Rockpaperscissors
{
    class Program
    {
        static void Main(string[] args)
        {
            string inputPlayer, Computer;
            int randomnum;
            string loop;
            bool keepPlaying = true;

            while (keepPlaying)
            {

                int wins = 0;
                int Loses = 0;
                int ties = 0;


                while (keepPlaying)
                {

                    Random myRandomObject = new Random();
                    randomnum = myRandomObject.Next(1, 4);
                    Console.Write("To play: enter R for Rock, S for Scissors, P for Paper.");
                    inputPlayer = Console.ReadLine();
                    inputPlayer = inputPlayer.ToUpper();

                    switch (randomnum)
                    {

                        case 1:
                            Computer = "Rock";
                            Console.WriteLine("The computer played Rock");
                            if (inputPlayer == "R")
                            {
                                Console.WriteLine("Tie!!\n\n");
                                ties++;
                            }
                            else if (inputPlayer == "P")
                            {
                                Console.WriteLine("You win!!\n\n");
                                wins++;
                            }
                            else if (inputPlayer == "S")
                            {
                                Console.WriteLine("Computer wins!!\n\n");
                                Loses++;
                            }
                            break;
                        case 2:
                            Computer = "Paper";
                            Console.WriteLine("The computer played Paper");
                            if (inputPlayer == "P")
                            {
                                Console.WriteLine("Tie!!\n\n");
                                ties++;
                            }
                            else if (inputPlayer == "R")
                            {
                                Console.WriteLine("Computer wins!!\n\n");
                                Loses++;
                            }
                            else if (inputPlayer == "S")
                            {
                                Console.WriteLine("You win!!\n\n");
                                wins++;
                            }
                            break;
                        case 3:
                            Computer = "Scissors";
                            Console.WriteLine("The computer played Scissors");
                            if (inputPlayer == "S")
                            {
                                Console.WriteLine("Tie!!\n\n");
                                ties++;
                            }
                            else if (inputPlayer == "R")
                            {
                                Console.WriteLine("You win!!\n\n");
                                wins++;
                            }
                            else if (inputPlayer == "P")
                            {
                                Console.WriteLine("Computer wins!!\n\n");
                                Loses++;
                            }
                            break;
                        default:                      
                            Console.WriteLine("Please enter a correct entry");  
                            break;
                    }

                    Console.WriteLine("Scores:\tWins:\t{0},\tLoses:\t{1},\tties:\t{2}", wins, Loses, ties);

                Console.WriteLine("Would you like to continue playing? (y/n)");
                loop = Console.ReadLine();
                if (loop == "y")
                {
                    keepPlaying = true;

                }
                else if (loop == "n")
                {
                    keepPlaying = false;
                }
                else
                {

                }

                }

            }

        }
    }
}

请帮忙!

【问题讨论】:

  • switch 语句不直接处理用户输入,因此不清楚您期望默认情况如何与之有任何关系。仅当开关进入其他情况之一时才检查用户输入。如果这样做,那么它将不会进入默认值。在这些不同的情况下,你有很多重复的代码。
  • 你学会并可以使用Function/Method了吗?
  • 另外,您似乎有两个 while 循环检查同一个变量,但也不确定这应该是什么。
  • 看看我对这个问题的回答:stackoverflow.com/questions/53746727/…。不是控制台应用,但逻辑​​应该是一样的
  • myRandomObject.Next(1, 4) 只会返回 1、2 或 3。因此不会达到默认情况。

标签: c#


【解决方案1】:

这是我在控制台应用程序中使用的一种方法,它很有帮助。我实际上有几个用于从用户那里获取类型(如int 或double)。它接受一个向用户显示的提示,并包含一个可选的验证器方法,它将针对输入运行以查看它是否有效。

这是一个用于字符串输入的:

public static string GetStringFromUser(string prompt, Func<string, bool> validator = null)
{
    var isValid = true;
    string result;

    do
    {
        if (!isValid)
        {
            WriteLineColor("Invalid input, please try again.", ConsoleColor.Red);
        }
        else isValid = false;

        Console.Write(prompt);
        result = Console.ReadLine();
    } while (validator != null && !validator.Invoke(result));

    return result;
}

在你的情况下,你可以简单地这样称呼它:

string playerInput = GetStringFromUser(
    "To play: enter R for Rock, S for Scissors, P for Paper: ",
    x => x.ToUpper() == "R" || x.ToUpper() == "S" || x.ToUpper() == "P");

Console.WriteLine($"You entered: {playerInput}");

Console.Write("\nPress any key to continue...");
Console.ReadKey();

这是示例输出:

【讨论】:

  • 不错的答案。注意:这些天,您可以跳过null 检查并直接执行!validator?.Invoke(result)。
  • @3Dave 差不多,除了它必须评估为bool,而不是bool?,所以你必须做类似(!validator?.Invoke(result) ?? false) 的事情,然后变得有点难以阅读.
【解决方案2】:

我建议在这样的数组中声明您的有效移动:

string[] validMoves = new string[3] { "R", "P", "S" };

然后在你的 switch 语句匹配之前,如果用户给出了一个有效或无效的输入,如果它无效则重新运行 while 循环,否则,继续 switch 语句。如下所示:

if (!validMoves.Contains(inputPlayer))
{
    Console.WriteLine("Please select a valid move.");
    continue;
}

这是您的主要方法的外观:
static void Main(string[] args)
{

    string inputPlayer, Computer;
    int randomnum;
    string loop;
    bool keepPlaying = true;
    string[] validMoves = new string[3] { "R", "P", "S" };
    int wins = 0;
    int Loses = 0;
    int ties = 0;
    while (keepPlaying)
    {
      // while (keepPlaying) // You can get rid of this while loop as it is not helping you out.
      // { // second while loop opening
            Random myRandomObject = new Random();
            randomnum = myRandomObject.Next(1, 4);
            Console.Write("To play: enter R for Rock, S for Scissors, P for Paper.");
            inputPlayer = Console.ReadLine();
            inputPlayer = inputPlayer.ToUpper();

            if (!validMoves.Contains(inputPlayer))
            {
                Console.WriteLine("Please select a valid move.");
                continue;
            }

            switch (randomnum)
            {
                case 1:
                    Computer = "Rock";
                    Console.WriteLine("The computer played Rock");
                    if (inputPlayer == "R")
                    {
                        Console.WriteLine("Tie!!\n\n");
                        ties++;
                    }
                    else if (inputPlayer == "P")
                    {
                        Console.WriteLine("You win!!\n\n");
                        wins++;
                    }
                    else if (inputPlayer == "S")
                    {
                        Console.WriteLine("Computer wins!!\n\n");
                        Loses++;
                    }
                    break;
                case 2:
                    Computer = "Paper";
                    Console.WriteLine("The computer played Paper");
                    if (inputPlayer == "P")
                    {
                        Console.WriteLine("Tie!!\n\n");
                        ties++;
                    }
                    else if (inputPlayer == "R")
                    {
                        Console.WriteLine("Computer wins!!\n\n");
                        Loses++;
                    }
                    else if (inputPlayer == "S")
                    {
                        Console.WriteLine("You win!!\n\n");
                        wins++;
                    }
                    break;
                case 3:
                    Computer = "Scissors";
                    Console.WriteLine("The computer played Scissors");
                    if (inputPlayer == "S")
                    {
                        Console.WriteLine("Tie!!\n\n");
                        ties++;
                    }
                    else if (inputPlayer == "R")
                    {
                        Console.WriteLine("You win!!\n\n");
                        wins++;
                    }
                    else if (inputPlayer == "P")
                    {
                        Console.WriteLine("Computer wins!!\n\n");
                        Loses++;
                    }
                    break;
                default: // You can get rid of this default block, it won't ever hit.
                    Console.WriteLine("Please enter a correct entry");
                    break;
            }

            Console.WriteLine("Scores:\tWins:\t{0},\tLoses:\t{1},\tties:\t{2}", wins, Loses, ties);

            Console.WriteLine("Would you like to continue playing? (y/n)");
            loop = Console.ReadLine();
            
            if (loop == "y")
            {
                keepPlaying = true;
            }
            else if (loop == "n")
            {
                keepPlaying = false;
            }
        // } // second while loop closing

    }
}

【讨论】:

    【解决方案3】:

    虽然这不能直接回答您的问题,但它应该显示请求用户输入并再次询问他们是否输入无效输入的程序的逻辑/流程。

                while (true)
                {
                    Console.WriteLine("1. Print A then C");
                    Console.WriteLine("2. Print B then C");
                    Console.Write("Enter option: ");
    
                    var input = Console.ReadLine();
                    switch (input)
                    {
                        case "1":
                            Console.WriteLine("A");
                            break;
                        case "2":
                            Console.WriteLine("B");
                            break;
                        default:
                            Console.WriteLine("Invalid Input. Please try again");
                            continue;
                    }
    
                    Console.WriteLine("C");
                }
    

    在这里,打印 A/B 就像选择你的手,而打印 C 就像显示结果。 default 分支使用 continue (see doc) 返回到循环的开头,因此不打印 C。

    【讨论】:

      【解决方案4】:

      如果您更喜欢面向对象的方法,下面是一个小示例。

      用法:dotnet 运行“你的名字”

      Program.cs

      using System;
      
      namespace RockPaperScissors
      {
          partial class Program
          {
              static void Main(string[] args)
              {           
                  StartGame(args);
              }
      
              static void StartGame(string[] args)
              {
                  var playerName = (args.Length == 1) ? args[0] : "Player 1";         
                  
                  var player1 = new Player(playerName);
                  var player2 = new ComputerPlayer();
      
                  var game = new RPSGame(player1, player2);
      
                  game.Init();
      
                  while (true)
                  {
                      game.DisplayAvailablePlay();
                      game.ReadPlayerInput();
      
                      if (!game.IsValidPlay())
                          continue;
      
                      game.Play();
      
                      game.DisplayResult();
                  }
                  
              }
          }
      }
      

      RPSGame.cs

      using System;
      
      namespace RockPaperScissors
      {
          internal partial class RPSGame
          {
              public RPSGame(Player firstPlayer, ComputerPlayer secondPlayer)
              {
                  Player1 = firstPlayer;
                  Player2 = secondPlayer;
              }
      
              internal GameStatus CurrentGameStatus = GameStatus.UnStarted;     
              internal int MatchDraws = 0;
      
              internal IPlayer Player1 { get; }
              internal IPlayer Player2 { get; }
              public IPlayer CurrentPlayer { get; private set; }
              public IPlayer Winner { get; private set; }
      
      
              internal void Init()
              {
                  SetStatus(GameStatus.Started);
                  SetCurrentPlayer(Player1);
                  Console.CancelKeyPress += Console_CancelKeyPress;
              }
      
              public void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e)
              {
                  this.SetStatus(GameStatus.Ended);
                  e.Cancel = true;
                  Environment.Exit(1);
              }
      
              internal void DisplayAvailablePlay()
              {
                  Console.WriteLine("To play: enter R for Rock, S for Scissors, P for Paper.");
                  Console.WriteLine("Press (Ctrl+C or Ctrl+Break) to Exit the game.");
              }
      
              internal void ReadPlayerInput()
              {
                  var playerSelectedKey = Console.ReadKey(false);
                  CurrentPlayer.SetSelectKey(playerSelectedKey.Key);
              }
      
              internal void DisplayResult()
              {
                  if (Winner != null)
                  {
                      Console.WriteLine();
                      Console.WriteLine("The Winner is:" + this.Winner.Name);
                      Console.WriteLine("Played:" + GetDisplayName(this.Winner.SelectedKey));
      
                  } else
                  {
                      Console.WriteLine("Draw!");
                      Console.WriteLine("You both Played:" + GetDisplayName(this.Player1.SelectedKey));
                  }
                  Console.WriteLine($"Your Score: wins({Player1.AmountWins}), losses({Player1.AmountLoss}), draws({MatchDraws})");
              }
      
              private string GetDisplayName(ConsoleKey selectedKey)
              {
                  return Enum.GetName(typeof(ConsoleKey), selectedKey);
              }
      
              internal void Play()
              {          
                  ((ComputerPlayer)Player2).GenerateRandomChoice();
                  SetWinner(Player1, Player2);
              }
      
              private void SetWinner(IPlayer player1, IPlayer player2)
              {
                  var differenceInState = player1.SelectedKey - player2.SelectedKey;
                  var generatedGameState = (GameState)Math.Abs(differenceInState);
      
                  switch (generatedGameState)
                  {
                      case GameState.RockScissor:
                          Winner = (differenceInState < 0) ? player1 : player2;
                          break;
                      case GameState.RockPaper:
                          Winner = (differenceInState < 0) ? player1 : player2;
                          break;
                      case GameState.PaperScissor:
                          Winner = (differenceInState < 0) ? player2 : player1;
                          break;
                      default:
                          Winner = null;
                          break;
                  }
      
                  UpdateStatistics();
                  SetStatus(GameStatus.Ended);
              }
      
              private void UpdateStatistics()
              {
                  if (Winner == Player1)
                  {
                      Player1.AmountWins++;
                      Player2.AmountLoss++;
                  }
                  else if (Winner == Player2)
                  {
                      Player2.AmountWins++;
                      Player1.AmountLoss++;
                  }
                  else
                  {
                      MatchDraws++;
                  }
              }
      
              internal bool IsValidPlay()
              {
                  switch (CurrentPlayer.SelectedKey)
                  {
                      case ConsoleKey.R:
                      case ConsoleKey.P:
                      case ConsoleKey.S:
                          return true;
                  }
                  return false;
              }
      
              private void SetCurrentPlayer(IPlayer currentPlayer)
              {
                  this.CurrentPlayer = currentPlayer;
              }
      
              private void SetStatus(GameStatus status)
              {
                  this.CurrentGameStatus = status;
              }
      
          }
      
      }
      

      BasePlayer.cs

      using System;
      
      namespace RockPaperScissors
      {
          class BasePlayer :  IPlayer
          {
              public ConsoleKey SelectedKey { get; set; }
              public string Name { get; set; }
              public int AmountWins { get; set; }
              public int AmountLoss { get; set; }
      
              public void SetSelectKey(ConsoleKey playerSelectedKey)
              {
                  SelectedKey = playerSelectedKey;
              }
          }
      
      }
      

      ComputerPlayer.cs

      using System;
      
      namespace RockPaperScissors
      {
          class ComputerPlayer : BasePlayer
          {        
              public ComputerPlayer()
              {
                  Name = "Computer Player";
                  GenerateRandomChoice();
              }
      
              public void GenerateRandomChoice()
              {
                  var rnd = new Random();
                  var choice = rnd.Next(1, 4);
                  switch(choice)
                  {
                      case 1:
                          SetSelectKey(ConsoleKey.R);
                          break;
                      case 2:
                          SetSelectKey(ConsoleKey.P);
                          break;
                      case 3:
                          SetSelectKey(ConsoleKey.S);
                          break;
                  }
              }
      
          }
      
      }
      

      GameState.cs

      namespace RockPaperScissors
      {
          public enum GameState
          {
              RockScissor = 1,
              RockPaper = 2,
              PaperScissor = 3,
          }
      }
      

      GameStatus.cs

      namespace RockPaperScissors
      {
          public enum GameStatus
          {
              UnStarted = 0,
              Started = 1,
              Ended = -1
          }
      }
      

      IPlayer.cs

      using System;
      
      namespace RockPaperScissors
      {
          interface IPlayer
          {
              public string Name { get; set; }
      
              public int AmountWins { get; set; }
              public int AmountLoss { get; set; }
      
              public ConsoleKey SelectedKey { get; set; }
      
              void SetSelectKey(ConsoleKey playerSelectedKey);
          }
      }
      

      Player.cs

      using System;
      
      namespace RockPaperScissors
      {
          class Player : BasePlayer
          {        
              public Player(string name)
              {
                  Name = name;
              }
          }
      }
      

      【讨论】:

        【解决方案5】:

        这是我对 RPS 游戏以及如何处理用户输入的看法。设计方面,我定义了几个 enum 类型来描述不同的动作或结果。

        public enum Move
        {
            Rock,
            Scissors,
            Paper,
        }
        
        public enum Outcome
        {
            Tie,
            Loss,
            Win,
        }
        

        然后我有两个辅助函数,一个用于处理用户输入(op 遇到问题的部分),另一个用于决定游戏,因为 op所有的重复都让我头疼。

        本着 int.TryParse(string, out int); 等 C# 函数的精神,我设计了 PlayerMove() 函数,如果成功则返回 true,否则返回 fase。函数的实际结果赋值给名为move的out变量。

        static class Program 
        {
            static readonly Random rng = new Random();
        
            // .. Main() goes here ==============
        
            /// <summary>
            /// Parses user input and decides what move was chosen if any.
            /// </summary>
            /// <param name="input">The user input.</param>
            /// <param name="move">The user move (output).</param>
            /// <returns>False if a move wasn't selected, true otherwise.</returns>
            static bool PlayerMove(string input, out Move move)
            {
                input = input.Trim().ToUpper();
                move = 0;
                if (string.IsNullOrWhiteSpace(input) || input.Length==0)
                {
                    return false;
                }
                switch (input[0])
                {
                    case 'R':
                        move = Move.Rock;
                        return true;
                    case 'P':
                        move = Move.Paper;
                        return true;
                    case 'S':
                        move = Move.Scissors;
                        return true;
                    default:
                        return false;
                }
            }
        
            /// <summary>
            /// Pick which combinations of plays wins for player, has a tie or a loss.
            /// </summary>
            /// <param name="player">The player move.</param>
            /// <param name="computer">The computer move.</param>
            /// <returns>The outcome of the game [Tie,Win,Loss]</returns>
            static Outcome DecideGame(Move player, Move computer)
            {
                if (player==computer)
                {
                    return Outcome.Tie;
                }
                else if ((player==Move.Rock && computer==Move.Scissors)
                    || (player==Move.Scissors && computer==Move.Paper)
                    || (player==Move.Paper && computer==Move.Rock))
                {
                    return Outcome.Win;
                }
                else
                {
                    return Outcome.Loss;
                }
            }
        }
        

        现在将游戏本身置于// Main() goes here 的上方。

        有一个变量keepPlaying 跟踪何时退出。主游戏循环是do { } while(keepPlaying); 循环。

        步骤是

        1. 提示用户
        2. 电脑随机选择Move
        3. 解析用户输入并分配玩家Move
        4. 如果用户没有进行有效的移动,请转到第 1 步
        5. 如果用户刚刚按下回车,那么input 包含一个空字符串并且游戏退出。
        6. 决定比赛结果
        7. 显示结果并调整赢/平/输数。

        下面的主要代码可以完成上述操作:

            static void Main(string[] args)
            {
                bool keepPlaying = true;
                int wins = 0, losses = 0, ties = 0;
                do
                {
                    Console.WriteLine();
                    Console.WriteLine($"Win={wins}, Loss={losses}, Tie={ties}");
                    Console.Write("To play: enter R for Rock, S for Scissors, P for Paper.");
                    var input = Console.ReadLine();                   
                    var computer = (Move)rng.Next(0, 3);
                    // Parse input and decide if the user made a move
                    // or wants to quit (invalid input or none).
                    if (PlayerMove(input, out Move player))
                    {
                        Console.Write($"Player: {player}, Computer: {computer} => ");
                        // Decide the outcome of the game here
                        Outcome game = DecideGame(player, computer);
                        switch (game)
                        {
                            case Outcome.Tie:
                                ties++;
                                Console.WriteLine("Tie");
                                break;
                            case Outcome.Loss:
                                losses++;
                                Console.WriteLine("loss");
                                break;
                            case Outcome.Win:
                                wins++;
                                Console.WriteLine("Win");
                                break;
                            default:
                                throw new NotSupportedException();
                        }
                    }
                    else
                    {
                        // stop when user just pressed enter.
                        keepPlaying = input.Length>0;
                    }
                } while (keepPlaying);
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-11-21
          • 1970-01-01
          • 2020-06-20
          • 2013-12-09
          • 1970-01-01
          • 2013-04-06
          • 2015-01-15
          相关资源
          最近更新 更多