AFF Education Construa seu Futuro

Aula 65 - Projeto Final: Jogo de Quiz

Aplicação completa integrando os conceitos do curso

Sobre este Projeto

Na última aula do curso, vamos construir um Jogo de Quiz interativo — um programa que desafia o usuário com 10 perguntas de múltipla escolha sobre Java, contabiliza o placar, embaralha a ordem das perguntas a cada partida e exibe uma avaliação final personalizada.

Este projeto é especialmente interessante porque usa arrays de Strings para armazenar perguntas e respostas, Collections.shuffle() para embaralhar, e demonstra como dados simples podem criar uma experiência interativa completa.

Como rodar no VSCode: Crie um arquivo chamado Quiz.java, cole o código completo, abra o terminal integrado (Ctrl + `) e execute com javac Quiz.java seguido de java Quiz.

Conceitos Aplicados Neste Projeto

Conceito Onde aparece no projeto Aulas relacionadas
Arrays de String Perguntas, alternativas (A/B/C/D) e gabaritos armazenados em arrays Aulas 47, 53, 55
Array bidimensional String[][] alternativas — cada linha tem 4 opções de resposta Aula 56
ArrayList + Collections Índices convertidos para ArrayList para poder usar Collections.shuffle() Aulas 57–59
For tradicional com índice Percorre as perguntas na ordem embaralhada usando o índice salvo Aula 41
Scanner Lê a resposta do jogador para cada pergunta Aula 17
Métodos personalizados jogar(), exibirPergunta(), avaliarDesempenho(), jogarNovamente() Aulas 34, 48
if-else encadeado Faixas de pontuação para classificar o desempenho do jogador Aulas 39–40
Operadores relacionais Compara a resposta do usuário com o gabarito Aulas 25–27
Incremento de variável acertos++ contabiliza o placar a cada resposta correta Aula 12
Métodos de String .toUpperCase().trim() normaliza a resposta digitada Aula 35
do-while Permite jogar novamente sem reiniciar o programa Aula 42
Especificadores de formato printf exibe o placar com formatação alinhada Aula 21

Estrutura de Dados: O Banco de Perguntas

O banco de perguntas usa três estruturas paralelas — todas com o mesmo índice representando a mesma pergunta:

Estrutura Tipo Conteúdo (exemplo — índice 0)
perguntas[i] String[] "Qual palavra-chave declara uma variável sem tipo fixo?"
alternativas[i] String[][] {"int", "var", "auto", "dynamic"}
gabaritos[i] String[] "B"

Array bidimensional alternativas: Cada posição alternativas[i] contém um array de 4 Strings — as opções A, B, C e D daquela pergunta. É como uma tabela: a linha escolhe a pergunta e a coluna escolhe a alternativa.

Código Completo — Quiz.java

import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;

public class Quiz {

    static Scanner sc = new Scanner(System.in);

    // ── BANCO DE PERGUNTAS ───────────────────────────────────────────────────

    static String[] perguntas = {
        "Qual palavra-chave declara uma variável sem tipo fixo em Java moderno?",
        "O que o operador % (módulo) retorna?",
        "Qual estrutura de dados armazena pares chave-valor?",
        "Para que serve o Scanner em Java?",
        "Qual é o valor padrão de um int[] criado com new int[5]?",
        "O que o for-each NÃO pode fazer em relação ao array?",
        "Qual é a diferença entre ArrayList e array simples?",
        "O que é uma constante em Java?",
        "O que o método .length() retorna em uma String?",
        "Qual loop garante que o bloco de código seja executado ao menos uma vez?"
    };

    // Array bidimensional: cada linha tem as 4 alternativas (A, B, C, D)
    static String[][] alternativas = {
        {"int", "var", "auto", "dynamic"},
        {"O resultado da multiplicação", "O resto da divisão inteira", "O quociente da divisão", "O valor absoluto"},
        {"Array", "ArrayList", "HashMap", "String[]"},
        {"Executar operações matemáticas", "Ler dados digitados pelo usuário", "Imprimir no terminal", "Criar arrays dinamicamente"},
        {"Valores aleatórios", "null", "0", "1"},
        {"Ler elementos", "Modificar os elementos do array original", "Percorrer todos os elementos", "Usar com ArrayList"},
        {"ArrayList tem tamanho fixo", "Array tem tamanho dinâmico", "ArrayList tem tamanho dinâmico e métodos extras", "São idênticos"},
        {"Uma variável que pode mudar a qualquer momento", "Uma variável declarada com final que não pode ser alterada", "Um método que retorna sempre o mesmo valor", "Um tipo primitivo do Java"},
        {"O número de caracteres da String", "A posição do último caractere", "O tamanho em bytes da String", "O número de palavras"},
        {"while", "for", "do-while", "for-each"}
    };

    // Gabarito: letra correta para cada pergunta (mesma posição que perguntas[])
    static String[] gabaritos = {"B", "B", "C", "B", "C", "B", "C", "B", "A", "C"};

    // ── MÉTODO PRINCIPAL ────────────────────────────────────────────────────
    public static void main(String[] args) {
        System.out.println("╔══════════════════════════════════════╗");
        System.out.println("║    BEM-VINDO AO QUIZ DE JAVA!        ║");
        System.out.println("║  10 perguntas · múltipla escolha     ║");
        System.out.println("╚══════════════════════════════════════╝");

        do {
            jogar();
            System.out.print("\nDeseja jogar novamente? (S/N): ");
        } while (sc.nextLine().trim().toUpperCase().equals("S"));

        System.out.println("\nObrigado por jogar! Continue praticando Java. 🚀");
        sc.close();
    }

    // ── JOGO PRINCIPAL ───────────────────────────────────────────────────────
    static void jogar() {
        int acertos = 0;

        // Cria uma lista de índices [0, 1, 2, ..., 9] e embaralha
        ArrayList<Integer> indices = new ArrayList<>();
        for (int i = 0; i < perguntas.length; i++) indices.add(i);
        Collections.shuffle(indices);

        // Percorre as perguntas na ordem embaralhada
        for (int q = 0; q < indices.size(); q++) {
            int idx = indices.get(q); // índice real da pergunta no banco

            System.out.println("\n─────────────────────────────────────────");
            System.out.printf("  Pergunta %d de %d%n", q + 1, perguntas.length);
            System.out.println("─────────────────────────────────────────");

            boolean respondeu = exibirPergunta(idx);

            if (respondeu) acertos++;
        }

        System.out.println("\n══════════════════════════════════════════");
        System.out.printf("  RESULTADO: %d de %d acertos (%.0f%%)%n",
            acertos, perguntas.length,
            (double) acertos / perguntas.length * 100);
        System.out.println("══════════════════════════════════════════");

        avaliarDesempenho(acertos);
    }

    // ── EXIBIR UMA PERGUNTA E VALIDAR RESPOSTA ──────────────────────────────
    static boolean exibirPergunta(int idx) {
        System.out.println("\n" + perguntas[idx]);
        System.out.println();

        // Exibe as alternativas usando o array bidimensional
        String[] letras = {"A", "B", "C", "D"};
        for (int j = 0; j < alternativas[idx].length; j++) {
            System.out.println("  " + letras[j] + ") " + alternativas[idx][j]);
        }

        System.out.print("\nSua resposta (A/B/C/D): ");
        String resposta = sc.nextLine().trim().toUpperCase();

        // Valida entrada
        while (!resposta.equals("A") && !resposta.equals("B")
            && !resposta.equals("C") && !resposta.equals("D")) {
            System.out.print("Entrada inválida. Digite A, B, C ou D: ");
            resposta = sc.nextLine().trim().toUpperCase();
        }

        if (resposta.equals(gabaritos[idx])) {
            System.out.println("✓ CORRETO!");
            return true;
        } else {
            System.out.println("✗ Incorreto. A resposta certa era: "
                + gabaritos[idx] + ") "
                + alternativas[idx][letraParaIndice(gabaritos[idx])]);
            return false;
        }
    }

    // ── CONVERTE LETRA EM ÍNDICE (A=0, B=1, C=2, D=3) ─────────────────────
    static int letraParaIndice(String letra) {
        switch (letra) {
            case "A": return 0;
            case "B": return 1;
            case "C": return 2;
            default:  return 3;
        }
    }

    // ── AVALIAÇÃO DO DESEMPENHO ──────────────────────────────────────────────
    static void avaliarDesempenho(int acertos) {
        if (acertos == 10) {
            System.out.println("🏆 PERFEITO! Você dominou o Java básico!");
        } else if (acertos >= 8) {
            System.out.println("🥇 Excelente! Você tem uma ótima base em Java.");
        } else if (acertos >= 6) {
            System.out.println("🥈 Muito bem! Revise alguns conceitos e você chega lá.");
        } else if (acertos >= 4) {
            System.out.println("🥉 Bom começo! Releia as aulas com mais dificuldade.");
        } else {
            System.out.println("📚 Continue praticando! A repetição é o segredo do aprendizado.");
        }
    }
}

╔══════════════════════════════════════╗

║ BEM-VINDO AO QUIZ DE JAVA! ║

║ 10 perguntas · múltipla escolha ║

╚══════════════════════════════════════╝

─────────────────────────────────────────

Pergunta 1 de 10

─────────────────────────────────────────

Qual é o valor padrão de um int[] criado com new int[5]?

A) Valores aleatórios

B) null

C) 0

D) 1

Sua resposta (A/B/C/D): C

✓ CORRETO!

─────────────────────────────────────────

Pergunta 2 de 10

─────────────────────────────────────────

O que o for-each NÃO pode fazer em relação ao array?

A) Ler elementos

B) Modificar os elementos do array original

C) Percorrer todos os elementos

D) Usar com ArrayList

Sua resposta (A/B/C/D): A

✗ Incorreto. A resposta certa era: B) Modificar os elementos do array original

...

══════════════════════════════════════════

RESULTADO: 8 de 10 acertos (80%)

══════════════════════════════════════════

🥇 Excelente! Você tem uma ótima base em Java.

Deseja jogar novamente? (S/N): N

Obrigado por jogar! Continue praticando Java. 🚀

Dica de extensão: Tente criar categorias de perguntas usando um String[] categorias = {"Variáveis", "Loops", ...} paralelo ao banco. Antes de cada pergunta, exiba a categoria. Depois, no resultado final, mostre o aproveitamento por categoria usando um HashMap<String, Integer> para contar acertos por tema.

Revisão dos Conceitos-Chave

🔀 Collections.shuffle()

Para embaralhar, convertemos os índices para um ArrayList<Integer> e usamos Collections.shuffle(). Arrays simples não têm esse método disponível diretamente — mais um ponto a favor do ArrayList quando precisamos de operações avançadas sobre coleções.

📐 Array bidimensional

alternativas[idx][j] acessa a alternativa j da pergunta idx. O primeiro índice escolhe a "linha" (pergunta) e o segundo a "coluna" (alternativa). Esse é exatamente o mesmo conceito de matrizes visto nas aulas anteriores.

✅ Validação de entrada

O loop while dentro de exibirPergunta() fica repetindo até que o usuário digite uma resposta válida (A, B, C ou D). Esse padrão — ler, validar, pedir novamente se inválido — é fundamental em qualquer programa que recebe dados do usuário.

↩️ Método retornando boolean

exibirPergunta() retorna true se o usuário acertou e false se errou. O método jogar() usa esse retorno para incrementar acertos++. Métodos com retorno são mais reutilizáveis do que métodos que apenas imprimem resultados.

🎓 Parabéns — Você Concluiu o Curso!

Ao longo de 65 aulas, você aprendeu os fundamentos essenciais de Java:

variáveis e tipos de dados → operadores → entrada com Scanner → métodos → estruturas de controle (if, for, while, switch) → arrays e matrizes → ArrayList → HashMap → classes e objetos → e três projetos reais completos.

Esses são os alicerces sobre os quais todo o desenvolvimento Java profissional é construído.

Próximos passos sugeridos: Com essa base, você está pronto para aprofundar em Orientação a Objetos (herança, encapsulamento, polimorfismo e interfaces), explorar tratamento de exceções com try-catch, e começar a trabalhar com Java para desenvolvimento web usando frameworks como Spring Boot.

Exercícios Finais

Última bateria de questões do curso — sobre o projeto Quiz e conceitos gerais:

1. Por que os índices das perguntas são convertidos para um ArrayList antes de usar Collections.shuffle()?

2. O que alternativas[2][1] acessa na estrutura do projeto?

3. Por que exibirPergunta() retorna boolean em vez de apenas imprimir o resultado?

4. O que acontece se o jogador digitar "x" como resposta?

5. Qual dos três projetos deste curso usa array bidimensional?

6. O método .toUpperCase().trim() é aplicado à resposta do jogador. Qual é o motivo?

7. Qual conceito, presente nos três projetos finais, mantém o menu ativo até o usuário decidir sair?

Exercícios de Aplicação AFF Education

Reforce o conteúdo desta aula com mais dois exercícios práticos:

1. Em um jogo de quiz, para guardar as perguntas e as alternativas correspondentes, uma boa estrutura é:

2. Para contabilizar a pontuação a cada resposta correta, deve-se: