Olá pessoal, alguém pode me ajudar, onde estou errando aqui?

Desafio:

Pedra, Papel, Ataque Aéreo é um jogo antigo mas que é popular até hoje. Nele, duas ou mais pessoas fazem gestos com a mão para vencer o adversário.

As partidas são muito simples. Os jogadores podem escolher entre o sinal de uma Pedra (o punho), o sinal de um Papel (a palma aberta), e o sinal para o Ataque Aéreo (igual o do Papel, mas com apenas o polegar e o mindinho estendidos).

Uma partida, com dois jogadores, possuem as seguintes regras para se definir um vencedor:

  • Ataque Aéreo vs. Pedra: Neste caso, o jogador com o Ataque Aéreo derrota o jogador com a Pedra, por razões óbvias.
  • Pedra vs. Papel: Neste caso, o jogador com a Pedra derrota o com Papel, porque a Pedra machuca muito mais.
  • Papel vs. Ataque Aéreo: Aqui o Ataque Aéreo ganha, porque Ataque Aéreo sempre ganha e o Papel é patético.
  • Papel vs. Papel: Nesta variação, ambos os jogadores ganham, porque o Papel é inútil e ninguém que enfrenta o Papel pode perder.
  • Pedra vs. Pedra: Para este caso não há ganhador, porque depende do que os jogadores decidem fazer com a Pedra e normalmente não fazem nada.
  • Ataque Aéreo vs. Ataque Aéreo: Quando isto acontece, todos os jogadores perdem, devido a Aniquilação Mútua.

Agora desenvolva um programa que, dada as escolhas de dois jogadores, informe quem venceu o jogo.

Entrada

A entrada consiste de N (1 ≤ N ≤ 1000) casos de teste. N deve ser lido na primeira linha da entrada. Cada caso de teste é composto por duas linhas, cada uma contendo uma string. A primeira string representa o sinal escolhido pelo jogador 1 e a segunda string representa o sinal escolhido pelo jogador 2. Essas strings podem ser:

  • “ataque”: para representar o Ataque Aéreo
  • “pedra”: para representar a Pedra
  • “papel”: para representar o Papel

Saída

A saída deve conter o seguinte:

  • “Jogador 1 venceu”: se o Jogador Um tiver vencido a partida
  • “Jogador 2 venceu”: se o Jogador Dois tiver vencido a partida
  • “Ambos venceram”: se os dois jogadores tiverem vencido a partida
  • “Sem ganhador”: se não houver ganhador
  • “Aniquilacao mutua”: se ocorrer Aniquilação Mútua

Cada saída de um caso de teste deve estar em uma linha.

Exemplo de Entrada:
2
pedra
pedra
ataque
papel

Exemplo de Saída:
Sem ganhador
Jogador 1 venceu

Esse é o código:


import java.util.*;
  
  public class Problem {
    public static void main(String[] args) {
        Scanner leitor = new Scanner(System.in);
        int N = leitor.nextInt();
        String jogador1, jogador2;
  
        for (int i = 0; i < N; i++) {
            jogador1 = leitor.next();
            jogador2 = leitor.next();
  
            if (jogador1.equalsIgnoreCase("ataque") && jogador2.equalsIgnoreCase("pedra"))
                System.out.println("Jogador 1 venceu");
            else if (jogador1.equalsIgnoreCase("pedra") && jogador2.equalsIgnoreCase("papel"))
                System.out.println("Jogador 1 venceu");
            else if (jogador1.equalsIgnoreCase("papel") && jogador2.equalsIgnoreCase("ataque"))
                System.out.println("Jogador 1 venceu");
            else if (jogador1.equalsIgnoreCase("pedra") && jogador2.equalsIgnoreCase("ataque"))
                System.out.println("Jogador 2 venceu");
            else if (jogador1.equalsIgnoreCase("papel") && jogador2.equalsIgnoreCase("pedra"))
                System.out.println("Jogador 2 venceu");
            else if (jogador1.equalsIgnoreCase("ataque") && jogador2.equalsIgnoreCase("papel"))
                System.out.println("Jogador 2 venceu");
            else if (jogador1.equalsIgnoreCase("papel") && jogador2.equalsIgnoreCase("papel"))
                System.out.println("Ambos venceram");
            else if (jogador1.equalsIgnoreCase("pedra") && jogador2.equalsIgnoreCase("pedra"))
                System.out.println("Sem ganhador");
            else if (jogador1.equalsIgnoreCase("ataque") && jogador2.equalsIgnoreCase("ataque"))
                System.out.println("Aniquilacao mutua");
        }
    }
  }

Problema: De acordo com o desafio, ele deve estar testando todas as jogadas possíveis de pedra, papel e ataque.

1 curtida

Qual o erro?

Ninguém vai se dar o trabalho de transcrever o código a partir de uma imagem.
Posta o seu código diretamente no fórum, assim todo mundo pode copiar e testar.
E não esqueça de formatar com o botão "</>".

Tem razão, já adicionei o código.

Aqui é o jogador 2 que venceu (ataque ganha da pedra e do papel).

Enfim, bastaria revisar uma a uma as possibilidades. Por exemplo, neste outro caso:

Foi o jogador 1 que venceu.


Dito isso, o exercício diz que as entradas serão minúsculas, então não precisaria usar equalsIgnoreCase. Mas se quiser garantir, poderia trocar a leitura para:

jogador1 = leitor.nextLine().toLowerCase();
jogador2 = leitor.nextLine().toLowerCase();

Assim, vc garante que trabalhará somente com minúsculas, e pode usar equals nas comparações.

Outro ponto é que não precisa verificar todas as possibilidades desta maneira. Claro que como são poucos casos (apenas 9 possibilidades), não fará tanta diferença. Mas e se fosse um jogo mais complexo, com mais possibilidades?

Ultimate rock paper scissors

Aí ficaria inviável testar um a um.

Então outra forma é verificar as possibilidades sem precisar testar tudo, e ir trabalhando por eliminação.

Por exemplo, primeiro eu vejo se ambas as jogadas são iguais, pois estes são casos especiais em que cada um dá um resultado diferente.

Depois eu vejo os casos em que as jogadas são diferentes, pois aí é mais tranquilo:

  • quem tem “ataque” sempre vence, então não preciso testar se o outro tem “pedra” ou “papel” (em ambos este perde, então é desnecessário verificar)
  • se nenhum tem “ataque”, quem tem “pedra” ganha

Ficaria assim (comentado para vc acompanhar o raciocínio):

// primeiro eu vejo os casos em que são iguais
if (jogador1.equals(jogador2)) {
    // se forem iguais, só preciso verificar um deles
    switch (jogador1) {
        case "ataque":
            System.out.println("Aniquilacao mutua");
            break;
        case "pedra":
            System.out.println("Sem ganhador");
            break;
        case "papel":
            System.out.println("Ambos venceram");
    }
} else { // agora eu vejo os casos em que são diferentes (e aqui, um deles ganhou)
    // ataque ganha da pedra e do papel, e como aqui eu sei que são diferentes (ou seja, se um tem ataque,
    // o outro com certeza não tem), não preciso verificar o outro
    if (jogador1.equals("ataque")) {
        System.out.println("Jogador 1 venceu");
    } else if (jogador2.equals("ataque")) {
        System.out.println("Jogador 2 venceu");
    } else {
        // se chegou aqui, é porque nenhum deles tem "ataque"
        // e como aqui eu já sei que são diferentes, então só preciso verificar qual tem a pedra
        if (jogador1.equals("pedra")) {
            System.out.println("Jogador 1 venceu");
        } else {
            // se chegou aqui é porque não são iguais, nenhum tem "ataque" e o jogador 1 não tem pedra
            // então a única possibilidade que restou é que o jogador 2 tenha a pedra, por isso nem precisa verificar
            System.out.println("Jogador 2 venceu");
        }
    }
}

Esta é essência do if/else. Se ele não entra em um if, quer dizer que aquela condição não foi satisfeita, então não é preciso verificá-la de novo no else correspondente. Sabendo disso vc vai eliminando possibilidades, e não precisa verificar de novo algo que vc já sabe que não vale naquele ponto do código.

E novamente, para este caso simples (apenas 9 possibilidades) talvez não simplifique tanto assim. Mas para um jogo mais complexo, testar tudo se torna inviável e vc teria que pensar em outras formas de avaliar (por exemplo, uma estrutura que mapeia quais opções cada um derrota, etc).