Un quiz para la terminal es un proyecto ideal para principiantes porque convierte conceptos básicos de Python en un programa interactivo completo. Las preguntas se guardan como datos, el usuario elige respuestas, el programa valida la entrada, calcula puntos y muestra un resultado final.
En esta guía construiremos un quiz en Python con preguntas de opción múltiple, respuestas mezcladas, validación, explicaciones, puntuación, repetición de partidas y carga opcional desde JSON.
Organizar los datos del quiz
Cada pregunta necesita un enunciado, una lista de opciones, la respuesta correcta y, opcionalmente, una explicación. Un diccionario representa una pregunta y una lista almacena el conjunto completo.
PREGUNTAS = [
{
"pregunta": "¿Qué palabra define una función en Python?",
"opciones": ["class", "def", "return", "import"],
"respuesta": "def",
"explicacion": "Las funciones comienzan con def.",
},
{
"pregunta": "¿Qué tipo almacena valores únicos?",
"opciones": ["list", "tuple", "set", "str"],
"respuesta": "set",
"explicacion": "Un set mantiene elementos únicos.",
},
]Guardar la respuesta como texto evita problemas cuando se mezclan las opciones.
Mostrar una pregunta
def mostrar_pregunta(pregunta, numero, total):
print()
print(f"Pregunta {numero} de {total}")
print(pregunta["pregunta"])
for numero_opcion, opcion in enumerate(
pregunta["opciones"],
start=1,
):
print(f" {numero_opcion}. {opcion}")enumerate() crea números para las opciones sin mantener un contador manual.
Leer y validar la respuesta
def leer_opcion(cantidad):
while True:
texto = input("Tu respuesta: ").strip()
try:
seleccion = int(texto)
except ValueError:
print("Introduce el número de una opción.")
continue
if 1 <= seleccion <= cantidad:
return seleccion - 1
print(f"Elige un número entre 1 y {cantidad}.")La función devuelve un índice válido para la lista. Los datos incorrectos no terminan el programa.
Comprobar la respuesta
def es_correcta(pregunta, indice):
seleccionada = pregunta["opciones"][indice]
return seleccionada == pregunta["respuesta"]Es una función pura: no solicita datos ni imprime. Eso facilita las pruebas.
Mezclar preguntas y opciones
import random
def preparar_preguntas(preguntas, generador=None):
generador = generador or random.Random()
preparadas = []
for pregunta in preguntas:
copia = {
**pregunta,
"opciones": list(pregunta["opciones"]),
}
generador.shuffle(copia["opciones"])
preparadas.append(copia)
generador.shuffle(preparadas)
return preparadasLa copia evita modificar el orden original. Puedes usar una semilla fija durante pruebas.
Calcular el porcentaje
def calcular_porcentaje(puntos, total):
if total == 0:
return 0.0
return puntos / total * 100Quiz completo en Python
import random
PREGUNTAS = [
{
"pregunta": "¿Qué palabra define una función en Python?",
"opciones": ["class", "def", "return", "import"],
"respuesta": "def",
"explicacion": "Las funciones comienzan con def.",
},
{
"pregunta": "¿Qué tipo almacena valores únicos?",
"opciones": ["list", "tuple", "set", "str"],
"respuesta": "set",
"explicacion": "Un set mantiene elementos únicos.",
},
{
"pregunta": "¿Qué devuelve len([10, 20, 30])?",
"opciones": ["2", "3", "30", "60"],
"respuesta": "3",
"explicacion": "len() devuelve la cantidad de elementos.",
},
{
"pregunta": "¿Qué estructura maneja excepciones?",
"opciones": ["if/else", "try/except", "for/in", "match/case"],
"respuesta": "try/except",
"explicacion": "try/except maneja errores durante la ejecución.",
},
]
def preparar_preguntas(preguntas, generador=None):
generador = generador or random.Random()
preparadas = []
for pregunta in preguntas:
copia = {
**pregunta,
"opciones": list(pregunta["opciones"]),
}
generador.shuffle(copia["opciones"])
preparadas.append(copia)
generador.shuffle(preparadas)
return preparadas
def mostrar_pregunta(pregunta, numero, total):
print()
print(f"Pregunta {numero} de {total}")
print(pregunta["pregunta"])
for numero_opcion, opcion in enumerate(pregunta["opciones"], start=1):
print(f" {numero_opcion}. {opcion}")
def leer_opcion(cantidad):
while True:
texto = input("Tu respuesta: ").strip()
try:
seleccion = int(texto)
except ValueError:
print("Introduce el número de una opción.")
continue
if 1 <= seleccion <= cantidad:
return seleccion - 1
print(f"Elige un número entre 1 y {cantidad}.")
def es_correcta(pregunta, indice):
return pregunta["opciones"][indice] == pregunta["respuesta"]
def calcular_porcentaje(puntos, total):
return puntos / total * 100 if total else 0.0
def jugar_quiz(preguntas, generador=None):
preparadas = preparar_preguntas(preguntas, generador)
puntos = 0
for numero, pregunta in enumerate(preparadas, start=1):
mostrar_pregunta(pregunta, numero, len(preparadas))
indice = leer_opcion(len(pregunta["opciones"]))
if es_correcta(pregunta, indice):
puntos += 1
print("¡Correcto!")
else:
elegida = pregunta["opciones"][indice]
print(f"Elegiste: {elegida}")
print(f"Respuesta correcta: {pregunta['respuesta']}")
explicacion = pregunta.get("explicacion")
if explicacion:
print(explicacion)
porcentaje = calcular_porcentaje(puntos, len(preparadas))
print()
print(f"Puntuación: {puntos}/{len(preparadas)}")
print(f"Porcentaje: {porcentaje:.1f}%")
if porcentaje == 100:
print("¡Puntuación perfecta!")
elif porcentaje >= 70:
print("¡Muy buen trabajo!")
elif porcentaje >= 50:
print("Buen comienzo. Revisa las explicaciones.")
else:
print("Sigue practicando e inténtalo otra vez.")
return puntos
def quiere_repetir():
while True:
respuesta = input("¿Jugar de nuevo? [s/n]: ").strip().lower()
if respuesta in {"s", "si", "sí"}:
return True
if respuesta in {"n", "no"}:
return False
print("Escribe s o n.")
def main():
print("Quiz de Python")
while True:
jugar_quiz(PREGUNTAS)
if not quiere_repetir():
print("¡Gracias por jugar!")
break
if __name__ == "__main__":
main()Cargar preguntas desde JSON
Separar las preguntas del código permite actualizar el contenido sin modificar la lógica.
[
{
"pregunta": "¿Qué palabra define una función?",
"opciones": ["class", "def", "return", "import"],
"respuesta": "def",
"explicacion": "Las funciones comienzan con def."
}
]import json
from pathlib import Path
def cargar_preguntas(ruta):
ruta = Path(ruta)
with ruta.open("r", encoding="utf-8") as archivo:
preguntas = json.load(archivo)
if not isinstance(preguntas, list):
raise ValueError("La raíz del JSON debe ser una lista.")
return preguntasValidar datos externos
def validar_preguntas(preguntas):
requeridos = {"pregunta", "opciones", "respuesta"}
for numero, pregunta in enumerate(preguntas, start=1):
faltantes = requeridos - pregunta.keys()
if faltantes:
raise ValueError(
f"Pregunta {numero}: faltan {sorted(faltantes)}"
)
if pregunta["respuesta"] not in pregunta["opciones"]:
raise ValueError(
f"Pregunta {numero}: la respuesta no está en las opciones"
)Probar la lógica
from quiz import calcular_porcentaje, es_correcta
def test_calcular_porcentaje():
assert calcular_porcentaje(4, 5) == 80.0
assert calcular_porcentaje(0, 0) == 0.0
def test_es_correcta():
pregunta = {
"opciones": ["list", "set"],
"respuesta": "set",
}
assert es_correcta(pregunta, 1) is True
assert es_correcta(pregunta, 0) is FalseErrores frecuentes
- Guardar solamente una letra de respuesta y después mezclar opciones.
- No validar los campos del JSON.
- Convertir la entrada sin manejar
ValueError. - Usar variables globales para toda la puntuación y el estado.
- Mezclar preguntas, salida, entrada y cálculo en un único bucle grande.
- Aceptar números fuera del rango disponible.
Ideas para mejorar
- Añadir categorías y niveles de dificultad.
- Seleccionar una cantidad limitada de preguntas.
- Guardar récords en JSON o SQLite.
- Añadir tiempo máximo por pregunta.
- Soportar preguntas de verdadero o falso.
- Crear una versión gráfica.
Conclusión
Un quiz en Python reúne estructuras de datos, bucles, validación, funciones, aleatoriedad, archivos y pruebas en un proyecto accesible. Separar los datos de la lógica facilita ampliar el juego sin volverlo difícil de mantener.
Lecturas relacionadas
- Organiza cada pregunta con la guía de diccionarios en Python.
- Comprende mejor la mezcla reproducible con el módulo random de Python.
- Automatiza la comprobación de funciones con la guía de Pytest para principiantes.
Documentación oficial
Consulta la documentación de Python sobre el módulo json y la referencia del módulo random utilizado para mezclar preguntas y opciones.




