java

Java – Ejercicio de cuestionario con preguntas, respuestas y porcentaje de aciertos

En este post vamos a resolver un ejercicio de programación en Java. No voy a poner un examen o cuestionario de Java; no. Vamos a resolver un ejercicio para implementar un cuestionario que recibe infinitas preguntas con infinitas respuestas en donde una de éstas es la correcta.

Luego, se le hace cada pregunta al usuario, se registra su respuesta y se van contando los aciertos así como los errores. Al final se muestra el porcentaje de errores y aciertos de acuerdo al total de preguntas.

Java – Implementación de un cuestionario o examen con preguntas, respuestas y resultados de aciertos con porcentajes

Resolveré este ejercicio propuesto en Java con programación orientada a objetos de la manera más elegante que pueda. Por cierto, el ejercicio dice así:

Tener un banco de preguntas, mínimo 12 con las 12 respuestas. Se pedirá que el usuario responda todas las preguntas. Una vez finalizado, se mostrará los resultados diciendo si la respuesta del usuario era correcta o no. También se mostrará el porcentaje de preguntas acertadas con decimales.

De hecho esto se parece a algo que ya había hecho tiempo atrás.

Funcionamiento general

Vamos a crear un programa que permite crear un cuestionario, agregarle varias preguntas (infinitas) con infinitas respuestas, indicando en las respuestas si la misma es correcta.

De este modo podemos crear varios exámenes con distinto número de preguntas y respuestas, permitiendo también crear infinitos cuestionarios.

La respuesta

Comencemos desde abajo. Una respuesta va dentro de una pregunta, y se debe indicar si la misma es correcta o no. Entonces tenemos la clase en Java:

class Respuesta {
    String respuesta;
    boolean esCorrecta;

    public Respuesta(String respuesta, boolean esCorrecta) {
        this.respuesta = respuesta;
        this.esCorrecta = esCorrecta;
    }

}

Solo tenemos la respuesta que es una cadena y un booleano indicando si la respuesta es correcta. Esto es porque al crear una pregunta vamos a agregarle varias respuestas pero solo una de ellas es la correcta.

Pregunta

Ahora pasemos a la pregunta. Una pregunta tiene varias respuestas, además de la pregunta en sí. La pregunta debe ser capaz de imprimirse a sí misma, recibir la respuesta del usuario e indicar si el usuario ha respondido correctamente.

Para ello tenemos el siguiente código:

class Pregunta {
    private final String pregunta;
    private final List<Respuesta> respuestas;

    // Nota: si crees que agregarás más respuestas, amplía las letras
    private static final String letras = "abcdefghijklmnñopqrstuvwxyz";

    public Pregunta(String pregunta, List<Respuesta> respuestas) {
        this.pregunta = pregunta;
        this.respuestas = respuestas;
    }

    public Pregunta(String pregunta) {
        this.pregunta = pregunta;
        this.respuestas = new ArrayList<>();
    }

    public void agregarRespuesta(Respuesta r) {
        this.respuestas.add(r);
    }

    public boolean respuestaCorrecta(char respuesta) {
        int indice = letras.indexOf(respuesta);
        if (indice == -1) {
            return false;
        }
        return this.respuestas.get(indice).esCorrecta;
    }

    public boolean preguntar(int numero) {
        System.out.println(numero + ". " + this.pregunta);
        int indice = 0;
        for (Respuesta r : this.respuestas) {
            System.out.printf("%c) %s\n", letras.charAt(indice), r.respuesta);
            indice++;
        }
        System.out.println("Elige: ");
        Scanner sc = new Scanner(System.in);
        char respuesta = sc.nextLine().charAt(0);
        return this.respuestaCorrecta(respuesta);
    }
}

Aquí las cosas empiezan a tomar forma. Vamos paso por paso. Como puedes ver, las respuestas son un ArrayList para que podamos tener una lista de tamaño variable.

Después tenemos métodos para agregar una respuesta, o también se puede indicar la lista de respuestas al construir el objeto; estamos sobrecargando el constructor.

También tenemos una función que nos dice si la respuesta es correcta, eligiendo el índice de la letra que ha elegido el usuario. Y finalmente tenemos el método preguntar que imprime la pregunta, imprime todas las posibles respuestas y lee lo que el usuario elija.

Es importante explicar la línea 39. En este caso estoy convirtiendo una cadena a char; ya que solo me interesa le primer carácter de toda la cadena (pues es la letra que el usuario introdujo).

El método de la línea 30 hace la pregunta y regresa un booleano indicando si la respuesta fue correcta. Este método lo usamos después dentro del cuestionario.

El cuestionario

Finalmente, un cuestionario se compone de varias preguntas, infinitas preguntas si lo queremos ver así, pero también lleva un conteo interno de los aciertos y errores.

Para el total de preguntas basta con medir la longitud de la lista, en este caso podemos obtenerlo con el método size del ArrayList.

class Cuestionario {
    private final List<Pregunta> preguntas;
    private int aciertos;
    private int errores;// ¿Alguien sabe el antónimo de acierto en este contexto? yo no


    public Cuestionario() {
        this.preguntas = new ArrayList<>();
    }

    public void agregarPregunta(Pregunta p) {
        this.preguntas.add(p);
    }

    public void preguntar() {
        int numero = 1;
        for (Pregunta p : this.preguntas) {
            boolean acierta = p.preguntar(numero);
            numero++;
            if (acierta) {
                System.out.println("Correcto");
                this.aciertos++;
            } else {
                System.out.println("Incorrecto");
                this.errores++;
            }
        }
    }

    public void imprimirResultados() {
        int total = this.preguntas.size();
        double porcentajeAciertos = (100 * (double) this.aciertos) / total;
        double porcentajeErrores = (100 * (double) this.errores) / total;
        System.out.printf("Total de preguntas: %d\nAciertos: %d (%.2f %%)\nErrores: %d (%.2f %%)", total, this.aciertos, porcentajeAciertos, this.errores, porcentajeErrores);
    }
}

La magia sucede en la línea 15; en este caso recorre todo el ArrayList e invoca a la función preguntar de cada pregunta… bellezas de la programación orientada a objetos.

También verifica si la respuesta es correcta, en ese caso aumenta los aciertos, y si no, aumenta los errores. Ya al final vemos a los resultados que básicamente calculan los porcentajes e imprimen los resultados.

El lector disculpará el uso de printf pero prefiero usar esa función que concatenar y convertir los valores.

Uso del programa

Ya vimos las 3 clases que nos permitirán hacer este simulador de cuestionario con preguntas, respuestas y estadísticas en Java. Veamos cómo usarlo, su uso es expresivo y elegante.

Por cierto, las respuestas correctas son solo de prueba, no quiero decir que yo esté en lo correcto.

public class Main {

    public static void main(String[] args) {
        Cuestionario c = new Cuestionario();
        c.agregarPregunta(new Pregunta("Lenguaje de programación más fácil de aprender", List.of(
                new Respuesta("Java", false),
                new Respuesta("Go", false),
                new Respuesta("Python", true),
                new Respuesta("JavaScript", false)
        )));
        c.agregarPregunta(new Pregunta("1 + 1", List.of(
                new Respuesta("3", false),
                new Respuesta("2", true),
                new Respuesta("4", false)
        )));
        c.agregarPregunta(new Pregunta("¿NetBeans es un lenguaje de programación?", List.of(
                new Respuesta("Sí", false),
                new Respuesta("No", true)
        )));

        c.agregarPregunta(new Pregunta("Lenguajes de programación (¡Miren! alguien dijo el chiste de que HTML no es un lenguaje de programación, ríanse) que sirven para programar en la web del lado del cliente", List.of(
                new Respuesta("HTML, CSS y JavaScript", true),
                new Respuesta("PHP, Python y JavaScript", false),
                new Respuesta("C y C++", false),
                new Respuesta("Perl y Kotlin", false),
                new Respuesta("Go, JavaScript y TypeScript", false)
        )));

        c.preguntar();
        c.imprimirResultados();
    }
}

Como puedes ver se debe crear una instancia de Cuestionario, y a partir de ahí invocar las veces que sea necesario a agregarPregunta. En este caso para hacerlo simple y no crear un ArrayList cada vez que creo una pregunta, estoy usando a List.of.

Poniendo todo junto

El código de Java completo queda así:

/*
  ____          _____               _ _           _       
 |  _ \        |  __ \             (_) |         | |      
 | |_) |_   _  | |__) |_ _ _ __ _____| |__  _   _| |_ ___ 
 |  _ <| | | | |  ___/ _` | '__|_  / | '_ \| | | | __/ _ \
 | |_) | |_| | | |  | (_| | |   / /| | |_) | |_| | ||  __/
 |____/ \__, | |_|   \__,_|_|  /___|_|_.__/ \__, |\__\___|
         __/ |                               __/ |        
        |___/                               |___/         
    
____________________________________
/ Si necesitas ayuda, contáctame en \
\ https://parzibyte.me               /
 ------------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
Creado por Parzibyte (https://parzibyte.me).
------------------------------------------------------------------------------------------------
Si el código es útil para ti, puedes agradecerme siguiéndome: https://parzibyte.me/blog/sigueme/
Y compartiendo mi blog con tus amigos
También tengo canal de YouTube: https://www.youtube.com/channel/UCroP4BTWjfM0CkGB6AFUoBg?sub_confirmation=1
------------------------------------------------------------------------------------------------
*/
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

class Respuesta {
    String respuesta;
    boolean esCorrecta;

    public Respuesta(String respuesta, boolean esCorrecta) {
        this.respuesta = respuesta;
        this.esCorrecta = esCorrecta;
    }

}

class Pregunta {
    private final String pregunta;
    private final List<Respuesta> respuestas;

    // Nota: si crees que agregarás más respuestas, amplía las letras
    private static final String letras = "abcdefghijklmnñopqrstuvwxyz";

    public Pregunta(String pregunta, List<Respuesta> respuestas) {
        this.pregunta = pregunta;
        this.respuestas = respuestas;
    }

    public Pregunta(String pregunta) {
        this.pregunta = pregunta;
        this.respuestas = new ArrayList<>();
    }

    public void agregarRespuesta(Respuesta r) {
        this.respuestas.add(r);
    }

    public boolean respuestaCorrecta(char respuesta) {
        int indice = letras.indexOf(respuesta);
        if (indice == -1) {
            return false;
        }
        return this.respuestas.get(indice).esCorrecta;
    }

    public boolean preguntar(int numero) {
        System.out.println(numero + ". " + this.pregunta);
        int indice = 0;
        for (Respuesta r : this.respuestas) {
            System.out.printf("%c) %s\n", letras.charAt(indice), r.respuesta);
            indice++;
        }
        System.out.println("Elige: ");
        Scanner sc = new Scanner(System.in);
        char respuesta = sc.nextLine().charAt(0);
        return this.respuestaCorrecta(respuesta);
    }
}

class Cuestionario {
    private final List<Pregunta> preguntas;
    private int aciertos;
    private int errores;// ¿Alguien sabe el antónimo de acierto en este contexto? yo no


    public Cuestionario() {
        this.preguntas = new ArrayList<>();
    }

    public void agregarPregunta(Pregunta p) {
        this.preguntas.add(p);
    }

    public void preguntar() {
        int numero = 1;
        for (Pregunta p : this.preguntas) {
            boolean acierta = p.preguntar(numero);
            numero++;
            if (acierta) {
                System.out.println("Correcto");
                this.aciertos++;
            } else {
                System.out.println("Incorrecto");
                this.errores++;
            }
        }
    }

    public void imprimirResultados() {
        int total = this.preguntas.size();
        double porcentajeAciertos = (100 * (double) this.aciertos) / total;
        double porcentajeErrores = (100 * (double) this.errores) / total;
        System.out.printf("Total de preguntas: %d\nAciertos: %d (%.2f %%)\nErrores: %d (%.2f %%)", total, this.aciertos, porcentajeAciertos, this.errores, porcentajeErrores);
    }
}

public class Main {

    public static void main(String[] args) {
        Cuestionario c = new Cuestionario();
        c.agregarPregunta(new Pregunta("Lenguaje de programación más fácil de aprender", List.of(
                new Respuesta("Java", false),
                new Respuesta("Go", false),
                new Respuesta("Python", true),
                new Respuesta("JavaScript", false)
        )));
        c.agregarPregunta(new Pregunta("1 + 1", List.of(
                new Respuesta("3", false),
                new Respuesta("2", true),
                new Respuesta("4", false)
        )));
        c.agregarPregunta(new Pregunta("¿NetBeans es un lenguaje de programación?", List.of(
                new Respuesta("Sí", false),
                new Respuesta("No", true)
        )));

        c.agregarPregunta(new Pregunta("Lenguajes de programación (¡Miren! alguien dijo el chiste de que HTML no es un lenguaje de programación, ríanse) que sirven para programar en la web del lado del cliente", List.of(
                new Respuesta("HTML, CSS y JavaScript", true),
                new Respuesta("PHP, Python y JavaScript", false),
                new Respuesta("C y C++", false),
                new Respuesta("Perl y Kotlin", false),
                new Respuesta("Go, JavaScript y TypeScript", false)
        )));

        c.preguntar();
        c.imprimirResultados();
    }
}

Puedes descargar el código y, como siempre, eres libre de modificarlo, compartirlo, mejorarlo, etcétera. Además, este programa también puede ser importado a NetBeans, IntelliJ IDEA, etcétera.

El ejemplo de ejecución lo dejé al inicio del post en la imagen. Finalmente te dejo más posts sobre Java en el blog de Parzibyte.

Estoy aquí para ayudarte 🤝💻


Estoy aquí para ayudarte en todo lo que necesites. Si requieres alguna modificación en lo presentado en este post, deseas asistencia con tu tarea, proyecto o precisas desarrollar un software a medida, no dudes en contactarme. Estoy comprometido a brindarte el apoyo necesario para que logres tus objetivos. Mi correo es parzibyte(arroba)gmail.com, estoy como@parzibyte en Telegram o en mi página de contacto

No te pierdas ninguno de mis posts 🚀🔔

Suscríbete a mi canal de Telegram para recibir una notificación cuando escriba un nuevo tutorial de programación.
parzibyte

Programador freelancer listo para trabajar contigo. Aplicaciones web, móviles y de escritorio. PHP, Java, Go, Python, JavaScript, Kotlin y más :) https://parzibyte.me/blog/software-creado-por-parzibyte/

Entradas recientes

Desplegar PWA creada con Vue 3, Vite y SQLite3 en Apache

Ya te enseñé cómo convertir una aplicación web de Vue 3 en una PWA. Al…

6 días hace

Arquitectura para wasm con Go, Vue 3, Pinia y Vite

En este artículo voy a documentar la arquitectura que yo utilizo al trabajar con WebAssembly…

6 días hace

Vue 3 y Vite: crear PWA (Progressive Web App)

En un artículo anterior te enseñé a crear un PWA. Al final, cualquier aplicación que…

6 días hace

Errores de Comlink y algunas soluciones

Al usar Comlink para trabajar con los workers usando JavaScript me han aparecido algunos errores…

6 días hace

Esperar promesa para inicializar Store de Pinia con Vue 3

En este artículo te voy a enseñar cómo usar un "top level await" esperando a…

6 días hace

Solución: Apache – Server unable to read htaccess file

Ayer estaba editando unos archivos que son servidos con el servidor Apache y al visitarlos…

7 días hace

Esta web usa cookies.