How can I ensure that the user makes the right choice?

I am making a simple program for working with paper scissors, but I'm not sure how to ensure that the user only makes the right choice. I need them to be able to reprofit them if they don’t type any kind of “rock”, “paper” or “scissors” (capitalization does not matter) and then “yes” or “no”. Suggestions?

import java.util.*; public class RockPaperScissors { private int wins = 0; private int losses = 0; private int ties = 0; public static void main(String[] args) { // TODO Auto-generated method stub RockPaperScissors model = new RockPaperScissors(); Scanner scan = new Scanner(System.in); while (true) { System.out.println("Rock, Paper, Scissors... Pick one! (Type Rock, Paper, or Scissors)"); String playerChoice = scan.next(); String computerChoice = model.getRandomChoice(); System.out.println("You chose " + playerChoice + "."); System.out.println("The computer chose " + computerChoice + "."); RockPaperScissors.GameOutcome outcome = model.getGameOutcome( playerChoice, computerChoice); if (outcome == RockPaperScissors.GameOutcome.WIN) { System.out.println("You won! Congratulations"); } else if (outcome == RockPaperScissors.GameOutcome.LOSE) { System.out.println("You lose! Better luck next time!"); } else { System.out.println("Tie!"); } System.out.print("Do you want to play again? (Yes/No):"); String answer = scan.next(); if (answer.equalsIgnoreCase("no")) { break; } } System.out.println("Thanks for playing!"); System.out.println("Wins: " + model.getWins()); System.out.println("Losses: " + model.getLosses()); System.out.println("Ties: " + model.getTies()); scan.close(); } public static enum GameOutcome { WIN, LOSE, TIE; } public GameOutcome getGameOutcome(String userChoice, String computerChoice) { if (userChoice.equalsIgnoreCase("Rock")) { if (computerChoice.equalsIgnoreCase("Paper")) { losses++; return GameOutcome.LOSE; } else if (computerChoice.equalsIgnoreCase("Scissors")) { wins++; return GameOutcome.WIN; } } else if (userChoice.equalsIgnoreCase("Paper")) { if (computerChoice.equalsIgnoreCase("Scissors")) { losses++; return GameOutcome.LOSE; } else if (computerChoice.equalsIgnoreCase("Rock")) { wins++; return GameOutcome.WIN; } } else if (userChoice.equalsIgnoreCase("Scissors")) { if (computerChoice.equalsIgnoreCase("Rock")) { losses++; return GameOutcome.LOSE; } else if (computerChoice.equalsIgnoreCase("Paper")) { wins++; return GameOutcome.WIN; } } ties++; return GameOutcome.TIE; } public String getRandomChoice() { double d = Math.random(); if (d < .33) { return "Rock"; } else if (d < .66) { return "Paper"; } else { return "Scissors"; } } public int getWins() { return wins; } public int getLosses() { return losses; } public int getTies() { return ties; } 

}

+5
source share
3 answers

If I were to play a roshambo session against the computer, I would like to make my choice only by typing the first letter "Rock", "Paper" or "Scissors".

Using rich enum is a natural choice here:

 private enum Choice { ROCK ("Rock"), PAPER ("Paper"), SCISSORS ("Scissors"); private String displayName; private static final List<Choice> VALUES = Collections.unmodifiableList(Arrays.asList(values())); private static final int SIZE = VALUES.size(); private static final Random RANDOM = new Random(); private Choice(String dn) { displayName = dn; } /** * Returns a random Choice. */ public static Choice getRandomChoice() { return VALUES.get(RANDOM.nextInt(SIZE)); } /** * Returns a Choice that matches the input string. The input is considered a match if it starts with the same character * as the displayname of a Choice. If no match is found, returns null. */ public static Choice fromInput(String input) { if (input == null || input.length() == 0) { return null; } for (Choice c : VALUES) { if (Character.toLowerCase(c.displayName.charAt(0)) == Character.toLowerCase(input.charAt(0))) { return c; } } return null; } /** * Returns the text to display to the user, asking for input to #fromInput(). */ public static String promptText() { StringBuilder sb = new StringBuilder(); for (Choice c : VALUES) { if (sb.length() > 0) { sb.append(", "); } sb.append(c.displayName).append(" (") .append(c.displayName.charAt(0)).append(")"); } sb.append(". Pick one!"); return sb.toString(); } } 

With most of the functionality declaratively encoded in enum , your client code will become much simpler. enum also handles random computer selection (idea from this answer).

  while (true) { Choice choice = null; while (choice == null) { System.out.println(Choice.promptText()); choice = Choice.fromInput(scan.next()); } String computerChoice = Choice.getRandomChoice().displayName; // ... 

You can also encapsulate most (if not all) of the logic available in the getGameOutcome method in Choice .

+3
source

Keep valid options in the list, the loop asks for input from the user until he enters something real.

 List<String> validChoices = Arrays.asList("rock", "paper", "scissors"); Scanner sc = new Scanner(System.in); String choice = null; do { System.out.println("Enter a choice (rock|paper|scissors)"); choice = sc.next().toLowerCase();//Retrieve as lower case } while(!validChoices.contains(choice)); 
+5
source

Somiting as

 if (!playerChoise.equalsIgnoreCase("paper") && ...) continue; 

Or you can save the actual options in a list as shown above and use the foreach loop. But it will be harder because you need to check all the options. Maybe something like.

 private boolean checkValid(String userChoise, String... variants) { for (String s : variants) { if (playerChoise.equalsIgnoreCase(s)) return true; } return false; } 

And call it for both cases:

 if (!checkValid(userChoise, "rock", "papper", "scissors")) continue; 
+1
source

All Articles