Rock, Paper, Scissors trong C #
Tôi đang thực hiện trò chơi Rock, paper, pull trong C # và hiện đang gặp sự cố khi cố hiển thị thông báo khi ai đó nhập đầu vào không phải là R, S hoặc P. Ví dụ: tôi đang cố gắng đặt mặc định trong nút chuyển tuyên bố để làm việc, nhưng không có may mắn. Đây là những gì tôi hiện có. Nếu có bất kỳ vấn đề nào khác mà tôi đã thực hiện, vui lòng cho tôi biết.
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
{
}
}
}
}
}
}
Hãy giúp tôi!
Trả lời
Đây là một phương pháp tôi đã sử dụng với các ứng dụng bảng điều khiển giúp ích rất nhiều. Tôi thực sự có một số trong số chúng để nhận các loại (như inthoặc double) từ người dùng. Nó có một lời nhắc, được hiển thị cho người dùng và bao gồm một phương thức xác thực tùy chọn mà nó sẽ chạy với đầu vào để xem liệu nó có hợp lệ hay không.
Đây là một cho đầu vào chuỗi:
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;
}
Trong trường hợp của bạn, bạn chỉ cần gọi nó như thế này:
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();
Và đây là kết quả đầu ra mẫu:
Tôi khuyên bạn nên khai báo các bước di chuyển hợp lệ của bạn trong một mảng như thế này:
string[] validMoves = new string[3] { "R", "P", "S" };
thì trước khi câu lệnh switch của bạn khớp nếu người dùng đã đưa ra một đầu vào hợp lệ hay không, nếu nó không hợp lệ thì hãy chạy lại whilevòng lặp, nếu không, hãy tiếp tục switchcâu lệnh. Một cái gì đó như dưới đây:
if (!validMoves.Contains(inputPlayer))
{
Console.WriteLine("Please select a valid move.");
continue;
}
Đây là cách phương thức chính của bạn sẽ trông như thế nào:
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
}
}
Mặc dù điều này không trực tiếp trả lời câu hỏi của bạn, nhưng nó sẽ hiển thị logic / luồng cho một chương trình yêu cầu đầu vào của người dùng và hỏi lại nếu họ nhập một đầu vào không hợp lệ.
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");
}
Ở đây, việc in A / B giống như chọn bàn tay của bạn, trong khi in C giống như hiển thị kết quả. Các defaultcông dụng chi nhánh continue( xem doc ) để trở về đầu vòng lặp và do đó không in C.
Nếu bạn thích cách tiếp cận hướng đối tượng hơn, dưới đây là một ví dụ nhỏ.
sử dụng: dotnet chạy "Tên của bạn"
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;
}
}
}
Đây là dự án của tôi về trò chơi RPS và cách xử lý đầu vào của người dùng. Thiết kế khôn ngoan, tôi đã xác định một số enumkiểu để mô tả các động thái hoặc kết quả khác nhau.
public enum Move
{
Rock,
Scissors,
Paper,
}
public enum Outcome
{
Tie,
Loss,
Win,
}
Sau đó, tôi có hai chức năng trợ giúp, một để xử lý đầu vào của người dùng (phần mà op gặp sự cố) và chức năng kia để quyết định trò chơi, vì op khiến tôi đau đầu với tất cả các lần lặp lại.
Theo tinh thần của các hàm C #, int.TryParse(string, out int);tôi đã thiết kế PlayerMove()hàm sao cho nó trả về truenếu thành công, và fasenếu không. Kết quả thực tế của hàm được gán cho outbiến có tên 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;
}
}
}
và bây giờ cho chính trò chơi được đặt ở trên nơi // Main() goes heređược chỉ định.
Có một biến keepPlayingtheo dõi thời điểm thoát. Vòng lặp trò chơi chính là một do { } while(keepPlaying);vòng lặp.
Các bước là
- Nhắc người dùng
- Máy tính chọn
Movengẫu nhiên - Phân tích cú pháp đầu vào của người dùng và chỉ định trình phát
Move - Nếu người dùng không thực hiện một động thái hợp lệ, hãy chuyển sang bước 1
- Nếu người dùng vừa nhấn enter, thì sẽ
inputchứa một chuỗi trống và trò chơi sẽ thoát. - Quyết định kết quả của trò chơi
- Hiển thị kết quả và điều chỉnh số lượng thắng / hòa / thua.
Và đoạn mã chính bên dưới để thực hiện những điều trên:
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);
}