C#でじゃんけん

Nov 21 2020

私はC#でじゃんけんゲームを作っていますが、現在、誰かがR、S、またはP以外の入力を入力したときにメッセージを表示しようとして問題が発生しています。たとえば、スイッチでデフォルトを取得しようとしています。動作するステートメントが、運がありません。これは私が現在持っているものです。他に問題がありましたらお知らせください。

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
                {

                }

                }

            }

        }
    }
}

助けてください!

回答

2 RufusL Nov 21 2020 at 09:11

これは私がコンソールアプリケーションで使用した方法で、非常に役立ちます。私は実際にユーザーからタイプ(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();

そして、これがサンプル出力です:

2 JamshaidK. Nov 21 2020 at 08:49

次のような配列で有効な移動を宣言することをお勧めします。

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

    }
}
1 LukeVo Nov 21 2020 at 08:15

これはあなたの質問に直接答えるものではありませんが、ユーザーの入力を要求し、ユーザーが無効な入力を入力したかどうかを再度尋ねるプログラムのロジック/フローを示す必要があります。

            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(ドキュメントを参照)、ループの先頭に戻りますので、Cを印刷しません。

Bruno Nov 21 2020 at 10:01

よりオブジェクト指向のアプローチを好む場合は、以下に小さな例を示します。

使用法:dotnet run "Your Name"

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;
        }
    }
}
JohnAlexiou Nov 22 2020 at 03:57

これは、RPSゲームとユーザー入力の処理方法に関する私の見解です。デザイン的には、enumさまざまな動きや結果を説明するためにいくつかのタイプを定義しました。

public enum Move
{
    Rock,
    Scissors,
    Paper,
}

public enum Outcome
{
    Tie,
    Loss,
    Win,
}

その後、私は2つのヘルパー関数、ユーザー入力(一部取り扱いのための1つ持っているopがあるため、ゲームを決定するための他のトラブルがあったが)opは私にすべての繰り返しで頭痛を与えます。

int.TryParse(string, out int);私のようなC#関数の精神で、成功した場合PlayerMove()は戻るtrueように、faseそうでない場合は返されるように関数を設計しました。関数の実際の結果は、outという名前の変数に割り当てられmoveます。

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. ユーザーがEnterキーを押したばかりの場合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);
    }