Rock, Paper, Scissors Game - Basic Game Simulation

Oct 03 2020

Gostei das muitas dores de cabeça que esse projeto me deu, pois aprendi muito! Tenho estudado Java há menos de um ano e sou novo na programação em geral. Eu li as regras de comentários e espero tê-las seguido corretamente. Não conheço muitas pessoas que codificam e adoraria qualquer feedback. Este foi um projeto escolar no qual trabalhei muito, mas sei que tenho um longo caminho a percorrer. Por favor, deixe-me saber se você pode me ajudar a melhorar ...

import java.util.Scanner;
    import java.util.Random;
    
    public class RPS {
        public static void main(String[] args) {
            Boolean playAgain = true;
            Scanner input = new Scanner(System.in);
            String play;
            
            while (playAgain = true) {      
            WelcomeP1(); //  Welcome & basic rule example
            
            // Final Result & Replay Option
            System.out.print("*********************" );
            System.out.print("-------------> You " +Game()+ "!!!" );
            System.out.println("\n*********************" );
            System.out.println("Play Again?!");
            System.out.println("Please press y for (Y)es or n for (N)o: ");
            play = input.nextLine().trim();
            while (play.isEmpty()){
                System.out.println("Do you want to play Rock, Paper, Scissors?");
                System.out.println("Please press y for (Y)es \nor n for (N)o: ");
                play = input
                        .nextLine().trim();
                } // end while ~ validate/catch error ~ for empty space
            switch ( play.charAt(0) ){
                    case 'n' : case 'N':
                        playAgain = false;
                        System.exit(0);
                    case 'y': case 'Y':
                        System.out.println("\n*********************" );
                        System.out.print("Excellent;\nGlad you enjoyed playing!"); 
                        System.out.println("\nJust checking again...");
              } // end while 
            } // end switch 
        } // end main
        
        
            // Welcome Validation Start
            public static void WelcomeP1(){
                Scanner stdIn= new Scanner(System.in);
                Boolean validGame = false;
                String userPlay;
                
                while( validGame == false ){
                System.out.println("Do you want to play Rock, Paper, Scissors?");
                System.out.println("Please press y for (Y)es \nor n for (N)o: ");
                userPlay = stdIn.nextLine().trim();
                while (userPlay.isEmpty()){
                    System.out.println("Do you want to play Rock, Paper, Scissors?");
                    System.out.println("Please press y for (Y)es \nor n for (N)o: ");
                    userPlay = stdIn.nextLine().trim();
                } // end while ~ validate/catch error ~ for empty space
                // below valiates user entry    
                switch ( userPlay.charAt(0) ){
                    case 'n' : case 'N':
                        System.exit(0);
                    case 'y': case 'Y':
                        validGame = true;
                        System.out.println("*************************************");
                        System.out.println("Excellent! Thank you...\nLet's Play!");
                        break;
                    default: 
                } // end switch
            } // end while loop 
            } // end class Welcome ~ End Welcome Validation
            
            
            // User Input Validation Start
            public static int P1Choice(){
                Scanner userIn = new Scanner(System.in);
                Boolean validUserIn = false;
                String userInput; 
                int userPiece = 0;
            
                while (validUserIn == false){
                    System.out.println("*************************************");
                    System.out.println("Choose (R)ock, (P)aper, or (S)cissors ");
                    System.out.println("Please type the first letter only.");
                    System.out.println("Your Choice: ");
                    userInput = userIn.nextLine();
                while (userInput.isEmpty()){
                    System.out.println("Choose (R)ock, (P)aper, or (S)cissors ");
                    System.out.println("Please type the first letter only.");
                    System.out.println("Your Choice: ");
                    userInput = userIn.nextLine();
                } // end while ~ validate/catch error ~ for empty space
                  // below valiates user entry further   
                    userPiece = userInput.charAt(0);
                if (userInput.equalsIgnoreCase("r")){
                    userPiece = 0;
                    System.out.println("You Chose: Rock");
                    validUserIn = true;
                }
                    else if (userInput.equalsIgnoreCase("p")){
                        userPiece = 1;
                        System.out.println("You Chose: Paper");
                        validUserIn = true;
                    }
                        else if (userInput.equalsIgnoreCase("s")) {
                            userPiece = 2;
                            System.out.println("You Chose: Scissors");
                            validUserIn = true;
                        }  
                        else {
                            System.out.println("Invalid Choice.");
                            validUserIn = false;
                        } 
                } // end while loop 
            return userPiece;
            } // end class UserPiece ~ End User Input Validation & Return
            
            
            // Computer Choice Calculation & Print ~ Start
            public static int ComputerChoice(){
            Random random = new Random();
            int choiceStart;
            choiceStart = random.nextInt(3); // max number 3 ~ 0-2
            int computerInput = 0;
            String computerPiece = null;
            
            switch (choiceStart) {
                case 0:
                    computerInput = 0; 
                    computerPiece = "Rock";
                    break;
                case 1:
                    computerInput = 1; //Paper
                    computerPiece = "Paper";
                    break;
                case 2:
                    computerInput = 2; //Scissors
                    computerPiece = "Scissors";
                    break;
            } // end switch
            System.out.println("*************************************");
            System.out.println("*************************************");
            System.out.println("The computer has decided as well...");
            System.out.println("|||||||||||||||||||||||||||||||||||||");
            System.out.println("|||||||||||||||||||||||||||||||||||||");
            System.out.println("The computer's choice was " +computerPiece+ "...");
            System.out.println("*************************************");
            System.out.println("*************************************");
            return computerInput;    
            } // end class ComputerChoice ~ End Computer Choice Calculation & Print
            
            
            // Calculate Game & Return Win/Loss/Tie ~ Calculations
            public static String Game(){
                int user = P1Choice();
                int computer = ComputerChoice();
                String error = "*** If you are reading this, there has been a"
                        +" system error. Please restart the program. ***";
                
                // 0 = rock
                // 1 = paper
                // 2 = scissors
                if (user == 0) {
                    if (computer != 1){
                        if (computer != 0){
                            return "Win";
                        }
                        return "Tie";
                    }
                    return "Lose";
                } // end first nested for loop logic
                if (user == 1){
                    if (computer != 2){
                        if (computer != 1) {
                            return "Win";
                        }
                        return "Tie";
                    }
                    return "Lose";       
                } // end second nested for loop logic
                if (user == 2){
                    if (computer != 0){
                        if (computer != 2) {
                            return "Win";
                        }
                        return "Tie";
                    }
                    return "Lose";       
                } // end third nested for loop logic
                return error; // null  -- Needed to return something 
                // -- better practice teacher?
            } // end class Game ~ End Calculate Game & Return     
    } // end class RPS

```

Respostas

10 user985366 Oct 03 2020 at 06:46

Formatação de código

Você tem alguns problemas de formatação e indentação. Execute seu código por meio de um formatador, por exemplo, este

https://www.tutorialspoint.com/online_java_formatter.htm

para torná-lo mais legível e seguir os padrões.

Lógica

while (playAgain = true) {

Isso está errado, deveria estar ==, não =. Funciona de qualquer maneira, pois o que você faz é apenas definir a playAgainvariável como truena primeira execução, que é o mesmo valor que já possui, e uma vez que durante o whileloop ele verifica o valor verdadeiro de playAgain.

while(playAgain) é equivalente a while(playAgain == true)

Comentários

    } // end while 
} // end switch 

Esses comentários estão na ordem errada. O switchestá dentro do while, por isso termina primeiro. Mas você não deve precisar desses comentários. Se você usar um bom editor de código e indentação adequada, verá facilmente (e obterá realce automático) em qual colchete corresponde a qual. Sugiro usar um editor como o IntelliJ ou o código do Visual Studio.

Lógica 2

O código de vitória / derrota / empate é muito longo e confuso.

Primeiro, para gravatas, você pode apenas verificar

if (user == computer) {
    return "Tie";
}

Isso cobre todas as combinações que criam um empate. Com esses casos fora do caminho, a lógica restante fica mais simples.

Já que o papel vence a pedra (1 vence o 0) e a tesoura vence o papel (2 vence 1), com suas convenientes definições de número você pode verificar user == computer + 1, mas também precisamos do estojo para pedra vence a tesoura.

if (user == computer + 1 || user == 0 && computer == 2) {
    return "Win";
}

Como agora cobrimos todos os casos de Empate ou Vitória, qualquer outro caso perderá

else {
    return "Lose";
}
8 Doi9t Oct 04 2020 at 07:45

Convenção de nomenclatura Java

O nome do método deve sempre começar com minúsculas.

  • WelcomeP1 -> welcomeP1
  • P1Choice -> p1Choice
  • ComputerChoice -> computerChoice
  • Game -> game

Use em java.io.PrintStream#printfvez de java.io.PrintStream#printlnquando você tiver que concatenar

java.io.PrintStream#printfoferecem a você o uso de padrões para construir a string sem concatená-la manualmente. A única desvantagem é que você mesmo será forçado a adicionar o caractere da linha de quebra; em java você pode usar o %npara quebrar a linha (portátil entre várias plataformas) ou usa o tradicional \n/ \r\n.

Antes

System.out.print("-------------> You " + game() + "!!!");

Depois de

System.out.printf("-------------> You %s!!!",  game());

Antes

System.out.println("The computer's choice was " + computerPiece + "...");

Depois de

System.out.printf("The computer's choice was %s...%n", computerPiece); //With a new line

Sempre use os primitivos quando possível

Quando você sabe que é impossível obter um valor nulo com o número, tente usar as primitivas; isso pode impedir o desempacotamento do valor em alguns casos.

Em seu código, você pode substituir o Booleana, booleanjá que possui apenas os valores truee false.

Extraia um pouco da lógica para métodos.

Quando você tem uma lógica que faz a mesma coisa, geralmente pode movê-la para um método e reutilizá-la.

Você pode extrair parte da lógica que pergunta se o usuário deseja jogar Pedra, Papel ou Tesoura em um método e reutilizá-lo.

private static String askIfWantToPlay(Scanner scanner) {
   String userPlay = "";
   while (userPlay.isEmpty()) {
      System.out.println("Do you want to play Rock, Paper, Scissors?");
      System.out.println("Please press y for (Y)es \nor n for (N)o: ");
      userPlay = scanner.next().trim();
   }
   return userPlay;
}

Este método removerá algumas duplicações.

Se quiser, você pode centralizar a lógica de saída neste novo método; verifique se o usuário deseja sair ou não.

private static void askIfWantToPlayAndExitOtherwise(Scanner scanner) {
   String userPlay = "";

   while (!"n".equalsIgnoreCase(userPlay) && !"y".equalsIgnoreCase(userPlay)) {
      System.out.println("Do you want to play Rock, Paper, Scissors?");
      System.out.println("Please press y for (Y)es \nor n for (N)o: ");
      userPlay = scanner.next();
   }

   if ("y".equalsIgnoreCase(userPlay)) {
      System.exit(0);
   } else {
      System.out.println("*************************************");
      System.out.println("Excellent! Thank you...\nLet's Play!");
   }
}

Com esse método, o código é mais fácil de ler e não propaga a lógica em todos os lugares do aplicativo; você pode fazer a mesma coisa com a escolha do usuário para a (R) ock, (P) aper ou (S) tesoura e retornar apenas uma escolha válida.

5 ZoranJankov Oct 06 2020 at 18:45

Posso concordar com todas as duas respostas anteriores, no entanto, tenho que abordar a questão da implementação da própria lógica do jogo. Acontece que entendemos a lógica do jogo porque todos nós conhecemos o jogo, mas se olharmos para o código, é difícil extrair a lógica do jogo do código. Não é escrito de forma limpa e fácil de entender, especialmente com ifaninhamento de declarações profundas .

public static String Game(){
                int user = P1Choice();
                int computer = ComputerChoice();
                String error = "*** If you are reading this, there has been a"
                        +" system error. Please restart the program. ***";
                
                // 0 = rock
                // 1 = paper
                // 2 = scissors
                if (user == 0) {
                    if (computer != 1){
                        if (computer != 0){
                            return "Win";
                        }
                        return "Tie";
                    }
                    return "Lose";
                } // end first nested for loop logic
                if (user == 1){
                    if (computer != 2){
                        if (computer != 1) {
                            return "Win";
                        }
                        return "Tie";
                    }
                    return "Lose";       
                } // end second nested for loop logic
                if (user == 2){
                    if (computer != 0){
                        if (computer != 2) {
                            return "Win";
                        }
                        return "Tie";
                    }
                    return "Lose";       
                } // end third nested for loop logic
                return error; // null  -- Needed to return something 
                // -- better practice teacher?
            } // end class Game ~ End Calculate Game & Return     
    } // end class RPS

Encontrei uma forma de implementar essa lógica de jogo de uma forma mais clara e fácil de ler e entender.

Use enumerações

Enumerações podem ajudar muito com clareza de código

public enum PlayedMove
{
    ROCK,
    PAPER,
    SCISSORS;
}

Eles são autoexplicativos

public enum Winer
{
    DRAW,
    PLAYER,
    COMPUTER;
}

A nova lógica do jogo

Como se você estivesse explicando isso para um homem e não para um computador

public class GameLogic
{
    public static Winer getWiner(PlayedMove player, PlayedMove computer)
    {
        if (player == computer)
        {
            return Winer.DRAW;
        }
        else if (isPlayerWiner(player, computer))
        {
            return Winer.PLAYER;
        }
        else
        {
            return Winer.COMPUTER;
        }
    }
    
    private static boolean isPlayerWiner(PlayedMove player, PlayedMove computer)
    {
        return ((player == PlayedMove.ROCK && computer == PlayedMove.SCISSORS)
             || (player == PlayedMove.SCISSORS && computer == PlayedMove.PAPER)
             || (player == PlayedMove.PAPER && computer == PlayedMove.ROCK));
    }
}