Problema codigo feito em Java?

Oi, estou com um problema em meu codigo, estou fazendo um jogo da forca em java, mas quando o codigo pede a primeira letra para o usuario, a letra soma(somente a primeira), ja a segunda letra e o restante funcionam normalmente.

import java.util.Scanner;
import java.util.Random;
import java.util.InputMismatchException;

public class Main {

    //FUNÇÃO VERDADEIRO OU FALSO, SE A "letraInserida" CONTEM DENTRO DA "palavraAleatoria", o metodo contains ele irá verificar se a sequencia de caracters está presente dentro da "palavraAleatoria", se estiver(true),caso não(false).
    public static boolean verificarLetras(String palavraAleatoria, String letraInserida) {
        return palavraAleatoria.contains(letraInserida);
    }

    public static String inserirLetras() {
        String letra;
        try {
            Scanner scanner = new Scanner(System.in);
            System.out.printf("Digite uma letra: ");
            letra = scanner.next().toLowerCase();

            if (!letra.matches("[a-z]")) { //matches -  Se o usuário digitar um elemento que tenha na sequência (a até z) será verdadeiro, caso contrário ele retornará um erro.
                throw new InputMismatchException("");
            }
        } catch (InputMismatchException err) {
            System.out.println("Entrada de dados inválida. Por favor, insira apenas uma letra de cada vez.");
            letra = inserirLetras(); // Chamada recursiva para pedir uma nova entrada
        }
        return letra;
    }

    // Método para gerar palavras aleatórias usando matriz
    public static String[] gerarPalavrasAleatorias() {
        Random random = new Random();
        String[][] palavra = {
                {"banana", "5"},
                {"programador", "20"},
                {"cachorro", "15"},
                {"bolacha", "18"},
                {"bicicleta", "10"},
        };
        String[] palavraAleatoria = palavra[random.nextInt(palavra.length)]; // Passando os dados da minha matriz para minha array palavraAleatoria
        return palavraAleatoria;
    }

    // Método onde, caso minha "palavraAleatoria" for uma das que estão nos cases, elas irão gerar uma dica para o usuário.
    public static void dicas(String palavraAleatoria) {
        System.out.print("DICA: ");
        switch (palavraAleatoria) {
            case "banana":
                System.out.println("FRUTA AMARELA.");
                break;
            case "programador":
                System.out.println("COMPUTADOR E SEU MELHOR AMIGO.");
                break;
            case "cachorro":
                System.out.println("ANIMAL DOMÉSTICO COM PELOS.");
                break;
            case "bolacha":
                System.out.println("COMESTÍVEL COM RECHEIO.");
                break;
            case "bicicleta":
                System.out.println("DUAS RODAS.");
                break;
            default:
                System.out.println("Sem dicas.");
        }
    }


    public static void main(String[] args) {
        Scanner scr = new Scanner(System.in);
        String continuar = "sim";

        int vida = 5;//VIDA JOGADOR.
        System.out.println("Seja Bem-Vindo ao Jogo Da Forca");
        System.out.printf("Insira seu nome:");//PEDINDO DADOS PARA O USUARIO.
        String nome = scr.next();

        while (continuar.equals("sim")) { //BLOCO WHILE, CASO MEU USUARIO DIGITE "SIM" MEU WHILE IRÁ FAZER UM LOOP POR TODO O CODIGO NOVAMENTE , CASO CONTRARIO ELE ENCERRA O BLOCO DE COMANDO.
            String[] pontuacao = gerarPalavrasAleatorias();

            //MINHA VARIAVEIS ESTÃO RECEBENDO MINHHSA PONTUAÇÕES QUE ESTÃO FIXIDAS NAS MINHAS PALAVRAS.
            String palavraAleatoria = pontuacao[0];
            String pontuacaoPalavra = pontuacao[1];

            dicas(palavraAleatoria);
            String letra = inserirLetras();

            String letrasInseridas = "";
            boolean palavraAdivinhada = false;

            while (vida > 0 && !palavraAdivinhada) { //BLOCO WHILE, NELE SE A VIDA DO JOGADOR FOR MAIOR QUE 0 OU DIFERENTE DA PALAVRADVINHADA O CODIGO CONTINUARÁ.
                //PAINEL DO JOGADOR
                System.out.println("");                 //Pula de linha
                System.out.println("PAINEL DO JOGADOR");
                System.out.println("");                 //Pula de linha
                System.out.println("SUA VIDA: " + vida); //MOSTRAR VIDA DO JOGADOR A CADA LOOP

                String letraInserida = inserirLetras();
                letrasInseridas += letraInserida;
                palavraAdivinhada = true;

                //BLOCO DE COMANDO ONDE ESTÁ VERIFICANDO SE A LETRA DIGITA CONTEM DENTRO DA MINHA "palavraAleatoria" CASO TENHA, "palavraAleatoria"  me retorna false

                for (int i = 0; i < palavraAleatoria.length(); i++) {
                    char letraChar = palavraAleatoria.charAt(i);
                    if (letrasInseridas.indexOf(letraChar) == -1) {
                        palavraAdivinhada = false;
                        break;
                    }
                }
                //BLOCO DE COMANDO ONDE ESTÁA VERIFICANDO SE A LETRA ATUAL"letraChar" está dentro da "palavraAleatoria" imprimimos ela na tela.
                for (int i = 0; i < palavraAleatoria.length(); i++) {
                    char letraChar = palavraAleatoria.charAt(i);
                    if (letrasInseridas.indexOf(letraChar) != -1) {
                        System.out.print(letraChar + " ");
                    } else {
                        System.out.print("_ ");       //CASO A LETRA NÃO ESTAJA, IMPRIMOS UM TROÇO ATÉ O USUARIO ACERTAR A LETRA.
                    }
                }

                System.out.println();

                //USUARIO ACERTOU A LETRA.
                if (verificarLetras(palavraAleatoria, letraInserida)) {
                    System.out.println("Parabéns, você acertou!!");
                }
                //USUARIO ERROU A LETRA.
                else if (letrasInseridas.contains(letraInserida)){
                    System.out.println("Letra já foi inserida.");
                    vida--;
                }
                else{
                    System.out.println("Letra " + letraInserida + " está incorreta.");
                    vida--; //SEMPRE QUE O USUARIO ERRA UMA LETRA  VIDA DIMINUI.
                }
            }

            //FINAL DO CODIGO, NELE IRÁ MOSTRAR SE O USUARIO ACERTOU A PALAVRA OU ERROU, PONTUAÇÃO DA PALAVRA, E SE DESEJA CONTINUAR OU NÃO.
            if (palavraAdivinhada) {
                System.out.println("Parabéns " + nome + " você descobriu a palavra!!");
            } else {
                System.out.println("Você perdeu, a palavra correta era: " + palavraAleatoria);
            }
            System.out.println("Sua pontuação:" + pontuacaoPalavra);
            System.out.println("Deseja continuar (sim/nao).");
            continuar = scr.next();

        }
        //ENCERRAMENTO, CASO O USUARIO ESCOLHA NÃO.
        System.out.println("Obrigado por jogar.");
    }
}

Substitua as chamadas do método next() por nextLine().

1 curtida

Sobre o problema em si (a primeira letra “some”), a solução é de fato usar nextLine como já dito (se quiser mais detalhes, escrevi uma explicação aqui). Mas aproveitando, tem outros detalhes que podem te ajudar:


Pelo que parece, a intenção aqui é que apenas uma letra seja lida, certo?

Só que chamar next (ou nextLine) não garante que somente uma letra será lida. Por exemplo, se eu digitar abc def (e depois ENTER), então next irá ler “abc” e nextLine irá ler tudo.

Uma alternativa para resolver é usar algo como char letra = Character.toLowerCase(scanner.next().charAt(0));, assim vc pega o primeiro caractere e ignora os demais. Desta forma fica até mais simples verificar se é uma letra:

char letra = Character.toLowerCase(scanner.next().charAt(0));
if ('a' <= letra && letra <= 'z') {
    System.out.println("É letra");
} else {
    System.out.println("Não é letra");
}

Se bem que assim só estamos verificando letras de “a” a “z” sem acento. Se a ideia é validar qualquer letra (de qualquer alfabeto, incluindo acentos, etc), poderia usar o que já tem pronto na classe Character. E claro, vc também poderia trocar por nextLine sem problema.

Outra abordagem é validar se foi digitado somente um caractere, por exemplo:

String linha = scanner.nextLine();
if (linha.length() == 1) {
    if (Character.isLetter(linha.charAt(0))) {
        System.out.println("É letra");
    } else {
        System.out.println("Não é letra");
    }
} else {
    System.out.println("Digite apenas um caractere");
}

Repare também que não precisa usar try/catch. Vc está usando exceções para controle de fluxo, o que é um uso torto. Exceções deveriam ser para situações excepcionais, e não para algo esperado (ser ou não ser uma letra são situações esperadas, e dá pra resolver com loops e condicionais). O mesmo vale para a chamada recursiva, que é um péssimo uso de recursão: se o usuário digitar dados errados muitas vezes, as chamadas recursivas vão se empilhando e pode estourar a pilha (sem contar que a cada chamada um novo Scanner é criado, o que é completamente desnecessário). Neste caso, o correto seria usar um loop, e criar apenas um Scanner (podendo inclusive ser um parâmetro, assim vc cria ele fora do método).

Ou seja, poderia ser assim:

public static String inserirLetras(Scanner scanner) {
    while (true) {
        System.out.printf("Digite uma letra: ");
        String linha = scanner.nextLine();
        if (linha.length() == 1) {
            if (Character.isLetter(linha.charAt(0))) {
                return linha.toLowerCase();
            } else {
                System.out.println("Entrada de dados inválida. Por favor, digite uma letra.");
            }
        } else {
            System.out.println("Entrada de dados inválida. Por favor, insira apenas uma letra de cada vez.");
        }
    }
}

E ao chamar o método, passe o Scanner que vc já criou no main, ou seja: String letra = inserirLetras(scr);.

Se bem que eu mudaria o nome do método para lerProximaLetra ou algo assim, já que ele não está inserindo nada…

Enfim, repare que agora não preciso mais de recursão: o while se repete enquanto não for digitada apenas uma letra. Se digitar mais que um caractere, ou se não for uma letra, ele mostra a mensagem e pede que se digite de novo. Raramente recursão é a solução mais adequada para casos assim.