Portada de libro electrónico gratuitaPython desde cero con mini-retos: aprende programando (sin teoría eterna)

Python desde cero con mini-retos: aprende programando (sin teoría eterna)

Nuevo curso

12 páginas

Mini-reto: juego de adivinanza con intentos y pistas

Capítulo 10

Tiempo estimado de lectura: 6 minutos

+ Ejercicio

Objetivo del mini-reto

Vas a construir un juego de adivinanza por consola: el programa elige un número secreto y la persona intenta adivinarlo con un número limitado de intentos. En cada intento, el juego da una pista (“más alto” o “más bajo”) y, opcionalmente, pistas extra según qué tan cerca esté el intento.

Qué vas a practicar aquí (sin repetir teoría)

  • Diseñar reglas del juego (intentos, rango, pistas) y convertirlas en pasos concretos.
  • Combinar entrada/salida por consola con validación práctica.
  • Controlar el estado de la partida: intentos restantes, mejor aproximación, fin por acierto o por agotamiento.
  • Usar aleatoriedad con random para generar el número secreto.

Reglas del juego (especificación mínima)

Define estas reglas antes de programar (puedes cambiarlas luego):

  • Rango del número secreto: por ejemplo, de 1 a 100.
  • Intentos máximos: por ejemplo, 7.
  • Pista básica: si el intento es menor que el secreto, decir “más alto”; si es mayor, “más bajo”.
  • Fin de partida: si acierta, gana; si se acaban los intentos, pierde y se revela el número.

Pistas extra (opcional, pero recomendado)

Además de “más alto/más bajo”, añade una pista de cercanía calculando la distancia absoluta entre el intento y el secreto.

  • Si la distancia es 0: acertó.
  • Si la distancia es <= 3: “¡Muy caliente!”
  • Si la distancia es <= 10: “Caliente”
  • Si la distancia es <= 20: “Tibio”
  • Si la distancia es mayor: “Frío”

Estos umbrales son configurables. Lo importante es que la pista dependa de un cálculo sencillo y consistente.

Paso a paso: versión base (más alto / más bajo)

1) Genera el número secreto

Usa el módulo estándar random para elegir un entero dentro del rango.

Continúa en nuestra aplicación.

Podrás escuchar el audiolibro con la pantalla apagada, recibir un certificado gratuito para este curso y además tener acceso a otros 5.000 cursos online gratuitos.

O continúa leyendo más abajo...
Download App

Descargar la aplicación

import random

min_n = 1
max_n = 100
secret = random.randint(min_n, max_n)

2) Define intentos y controla el bucle de juego

Necesitas un contador de intentos restantes y un bucle que se repita mientras queden intentos y no se haya acertado.

max_tries = 7
tries_left = max_tries
won = False

3) Pide un número y valida que esté en rango

La entrada debe convertirse a entero y además debe estar dentro del rango. Si no lo está, no debería consumir un intento (decisión típica en juegos). Aquí se muestra una forma práctica: repetir la petición hasta obtener un entero válido en rango.

def ask_int_in_range(prompt, min_n, max_n):
    while True:
        raw = input(prompt)
        try:
            n = int(raw)
        except ValueError:
            print("Entrada inválida: escribe un número entero.")
            continue

        if n < min_n or n > max_n:
            print(f"Fuera de rango: debe estar entre {min_n} y {max_n}.")
            continue

        return n

4) Compara y muestra la pista

En cada intento: pedir número, comparar con el secreto, dar pista y actualizar intentos restantes.

import random

def ask_int_in_range(prompt, min_n, max_n):
    while True:
        raw = input(prompt)
        try:
            n = int(raw)
        except ValueError:
            print("Entrada inválida: escribe un número entero.")
            continue
        if n < min_n or n > max_n:
            print(f"Fuera de rango: debe estar entre {min_n} y {max_n}.")
            continue
        return n

min_n = 1
max_n = 100
secret = random.randint(min_n, max_n)

max_tries = 7
tries_left = max_tries
won = False

print(f"Adivina el número entre {min_n} y {max_n}. Tienes {max_tries} intentos.")

while tries_left > 0 and not won:
    guess = ask_int_in_range(f"Intento ({tries_left} restantes): ", min_n, max_n)

    if guess == secret:
        won = True
        print("¡Correcto!")
    else:
        tries_left -= 1
        if guess < secret:
            print("Pista: más alto.")
        else:
            print("Pista: más bajo.")

if not won:
    print(f"Se acabaron los intentos. El número era {secret}.")

Mejora 1: pistas de cercanía (frío/tibio/caliente)

Agrega una función que traduzca la distancia a una etiqueta. Esto hace el juego más “jugable” sin complicarlo.

def heat_hint(distance):
    if distance == 0:
        return "¡Exacto!"
    if distance <= 3:
        return "¡Muy caliente!"
    if distance <= 10:
        return "Caliente"
    if distance <= 20:
        return "Tibio"
    return "Frío"

Luego, dentro del bucle, calcula la distancia y muestra la pista adicional cuando no acierta:

distance = abs(guess - secret)
print(f"Cercanía: {heat_hint(distance)}")

Mejora 2: no repetir intentos y dar pista “repetido”

Evita que la persona desperdicie intentos repitiendo el mismo número. Guarda los intentos usados en una colección (por ejemplo, un set) y, si se repite, avisa y no descuentes intento.

used = set()

# dentro del bucle, después de leer guess:
if guess in used:
    print("Ya probaste ese número. Elige otro.")
    continue
used.add(guess)

Mejora 3: modo difícil (rango dinámico)

Una pista potente es ir “cerrando” el rango posible según las respuestas. Si el intento fue menor que el secreto, el mínimo posible sube; si fue mayor, el máximo baja. Así el juego se siente más inteligente.

current_min = min_n
current_max = max_n

# dentro del bucle, cuando no acierta:
if guess < secret:
    current_min = max(current_min, guess + 1)
    print(f"Pista: más alto. Nuevo rango: {current_min}-{current_max}")
else:
    current_max = min(current_max, guess - 1)
    print(f"Pista: más bajo. Nuevo rango: {current_min}-{current_max}")

Si aplicas rango dinámico, también conviene validar la entrada contra current_min y current_max en lugar del rango original.

Checklist de pruebas rápidas (para que no se rompa)

  • Entrada no numérica: el juego debe pedir de nuevo sin gastar intento.
  • Número fuera de rango: debe pedir de nuevo sin gastar intento.
  • Acierto en el primer intento: debe terminar inmediatamente.
  • Agotar intentos: debe revelar el secreto.
  • Si activas “no repetir”: repetir un número no debe gastar intento.
  • Si activas rango dinámico: el rango mostrado debe encogerse correctamente y la validación debe respetarlo.

Mini-retos extra (elige 1)

  • Marcador por puntos: empieza con 100 puntos y resta según la distancia en cada fallo (por ejemplo, restar abs(guess-secret) con un mínimo de 1).
  • Dos modos: “Fácil” (más alto/más bajo) y “Difícil” (rango dinámico + pistas de cercanía).
  • Semilla reproducible: permite pasar una semilla (seed) opcional para depurar partidas (si el usuario escribe vacío, usar aleatorio).
  • Récord personal: guarda el menor número de intentos usados en la sesión (solo mientras el programa está abierto).

Ahora responde el ejercicio sobre el contenido:

En un juego de adivinanza con validación de entrada y rango, ¿qué comportamiento es el más adecuado cuando la persona ingresa un valor no numérico o fuera del rango permitido?

¡Tienes razón! Felicitaciones, ahora pasa a la página siguiente.

¡Tú error! Inténtalo de nuevo.

La validación debe evitar penalizar errores de formato o valores fuera del rango: se repite la solicitud hasta obtener un entero en rango, manteniendo intactos los intentos para que el juego sea justo y consistente.

Siguiente capítulo

Lectura y escritura de archivos para persistencia de datos

Arrow Right Icon
Descarga la aplicación para obtener una certificación gratuita y escuchar cursos en segundo plano, incluso con la pantalla apagada.