Roche, papier, ciseaux en C #
Je crée un jeu Rock, papier, ciseaux en C # et j'ai actuellement du mal à afficher un message lorsque quelqu'un entre une entrée qui n'est pas R, S ou P. Par exemple, j'essaie d'obtenir la valeur par défaut dans le commutateur déclaration au travail, mais je n'ai pas de chance. C'est ce que j'ai actuellement. S'il y a d'autres problèmes que j'ai rencontrés, veuillez me le faire savoir.
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
{
}
}
}
}
}
}
Veuillez aider!
Réponses
Voici une méthode que j'ai utilisée avec les applications console qui m'aide beaucoup. J'en ai en fait plusieurs pour obtenir des types (comme int
ou double
) de l'utilisateur. Il prend une invite, qui est affichée à l'utilisateur et inclut une méthode de validation facultative qu'il exécutera sur l'entrée pour voir si elle est valide.
En voici un pour l'entrée de chaîne:
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;
}
Dans votre cas, vous l'appelleriez simplement comme ceci:
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();
Et voici l'exemple de sortie:

Je suggérerais de déclarer vos mouvements valides dans un tableau comme celui-ci:
string[] validMoves = new string[3] { "R", "P", "S" };
puis avant que votre instruction switch ne corresponde si l'utilisateur a donné une entrée qui est valide ou non, si elle n'est pas valide, réexécutez la while
boucle, sinon continuez à l' switch
instruction. Quelque chose comme ci-dessous:
if (!validMoves.Contains(inputPlayer))
{
Console.WriteLine("Please select a valid move.");
continue;
}
Voici à quoi devrait ressembler votre méthode principale:
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
}
}
Bien que cela ne réponde pas directement à votre question, il doit afficher la logique / le flux d'un programme qui demande l'entrée de l'utilisateur et lui demande à nouveau s'il saisit une entrée non valide.
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");
}
Ici, imprimer A / B c'est comme choisir sa main, tandis qu'imprimer C c'est comme montrer le résultat. La default
branche utilise continue
( voir doc ) pour revenir au début de la boucle et n'imprime donc pas C.

Si vous préférez une approche plus orientée objet, voici un petit exemple ci-dessous.
utilisation: dotnet exécutez "Votre nom"
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;
}
}
}
C'est mon point de vue sur le jeu RPS et comment gérer les entrées des utilisateurs. Du point de vue du design, j'ai défini quelques enum
types pour décrire différents mouvements ou résultats.
public enum Move
{
Rock,
Scissors,
Paper,
}
public enum Outcome
{
Tie,
Loss,
Win,
}
Ensuite , j'ai deux fonctions d'aide, un pour traiter l'entrée d'utilisateur (la partie du op a eu du mal avec) et l'autre pour décider du jeu, parce que l' op me donne un mal de tête avec toute la répétition.
Dans l'esprit des fonctions C # telles que int.TryParse(string, out int);
j'ai conçu la PlayerMove()
fonction de telle sorte qu'elle retourne en true
cas de succès, et fase
sinon. Le résultat réel de la fonction est affecté à la out
variable nommée 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;
}
}
}
et maintenant pour que le jeu lui-même soit placé au-dessus de l'endroit où // Main() goes here
est indiqué.
Il y a une variable keepPlaying
qui garde une trace du moment de quitter. La boucle principale du jeu est une do { } while(keepPlaying);
boucle.
Les étapes sont
- Inviter l'utilisateur
- L'ordinateur choisit
Move
au hasard - Analyser les entrées de l'utilisateur et attribuer un joueur
Move
- Si l'utilisateur n'a pas effectué de déplacement valide, passez à l'étape 1
- Si l'utilisateur vient d'appuyer sur Entrée,
input
contient une chaîne vide et le jeu se ferme. - Décidez du résultat du jeu
- Affichez le résultat et ajustez le nombre de victoires / égalités / défaites.
Et le code principal ci-dessous pour faire ce qui précède:
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);
}