Este tutorial es una adaptación pedagógica del Día 4. Las secciones 📝 Ejercicio original del curso provienen de los archivos del curso. Los retos 🟢🟡🟠🔴, el proyecto extra y el proyecto integrador son creaciones de esta adaptación. Las correcciones al material original aparecen como 🛠️ Nota técnica.
Tabla de contenidos
- Antes de empezar
- El módulo
randomy los módulos en Python - Listas: índices, modificación y
append() IndexErrory listas anidadas- 🚀 Proyecto del día: Piedra, Papel o Tijera
- 🌟 Proyecto extra: Sorteo de la Semana de la Ciencia
- 🏆 Proyecto integrador del Día 4: Piedra, Papel, Tijera, Lagarto, Spock
- 🤖 Programar con apoyo de IA
- 🛠️ Correcciones técnicas al material original
- 📋 Matriz de trazabilidad
- 📦 Evidencias de aprendizaje del Día 4
0. Antes de empezar
(Fuente: 030 - Day 4 Goals- what we will make by the end of the day.md, 036 - Programming is like going to the Gym.md)
Hoy aprenderemos a hacer que el computador tome decisiones al azar y a guardar muchos datos relacionados en una sola variable. Con eso construiremos un juego de Piedra, Papel o Tijera contra el computador.
El mensaje motivacional del curso para hoy: programar es como ir al gimnasio. Nadie gana músculo viendo videos de ejercicio. Solo se aprende escribiendo código todos los días.
Prerequisito general: Días 1 a 3, en especial
if/elif/else, operadores lógicos,int(input())y subíndices de strings (Día 2, Tema 1).
1. El módulo random y los módulos en Python
(Fuente: 031 - Random Module.md)
Prerequisito: funciones (
len,round),if/else(Día 3).
🎯 Objetivo de aprendizaje
- Importar y usar el módulo
randompara generar números enteros y decimales al azar. - Explicar qué es un módulo y crear uno propio.
- Consultar la documentación oficial para descubrir funciones nuevas.
🧠 ¿Qué aprenderemos?
- Aleatoriedad y números pseudoaleatorios.
import, módulos y la notación con punto (random.randint).random.randint(a, b),random.random()yrandom.uniform(a, b).
📖 Explicación conceptual
¿Por qué necesitamos aleatoriedad? Un Tetris en el que siempre cayera la misma secuencia de piezas no tendría gracia. Los juegos, los sorteos y las simulaciones necesitan imprevisibilidad.
Sin embargo, los computadores son deterministas: ante las mismas instrucciones hacen siempre lo mismo. Para simular el azar usan fórmulas matemáticas llamadas generadores de números pseudoaleatorios. Python usa uno llamado Mersenne Twister. No necesitamos programarlo: el equipo de Python ya lo hizo y lo dejó listo en el módulo random.
¿Qué es un módulo? Es un archivo de Python con código listo para reutilizar. Así como en una fábrica de carros un equipo arma el motor y otro las llantas, un programa grande se divide en módulos, cada uno responsable de una parte del trabajo.
import random # 1. Importar el módulo
numero = random.randint(1, 10) # 2. Usar una función: módulo.función()
print(numero)Funciones principales
| Función | Qué devuelve | ¿Incluye los extremos? | Ejemplo |
|---|---|---|---|
random.randint(a, b) |
Entero entre a y b |
Sí, incluye a y b |
randint(1, 6) es un dado |
random.random() |
Decimal entre 0 y 1 | Incluye 0, nunca 1 | 0.7314... |
random.uniform(a, b) |
Decimal entre a y b |
Incluye a; incluir b depende del redondeo |
uniform(1, 10) |
random.random() no recibe datos de entrada, pero igual necesita paréntesis vacíos () para ejecutarse. Para ampliar su rango se multiplica: random.random() * 10 da un decimal entre 0 y 10, sin incluir el 10.
Crear tu propio módulo
- Crea un archivo
mi_modulo.pyen la misma carpeta de tu programa. - Escribe dentro
numero_favorito = 3.1415. - En tu archivo principal (por ejemplo
main.py):
import mi_modulo
print(mi_modulo.numero_favorito) # 3.1415Funciona exactamente igual que random: import + nombre del módulo + punto + lo que quieres usar.
🔎 Ejemplo explicado: lanzar un dado
import random
dado = random.randint(1, 6)
print(f"Sacaste un {dado}")
if dado == 6:
print("¡Vuelves a lanzar!")- Qué problema resuelve: simula un dado para un juego de mesa.
- Por qué
randint(1, 6): ambos extremos están incluidos, así que los resultados posibles son 1, 2, 3, 4, 5 y 6. - Resultado esperado: cambia en cada ejecución. Con muchas ejecuciones, cada cara debería salir más o menos 1 de cada 6 veces.
⚠️ Errores frecuentes
1. Olvidar el import
- Qué ocurre:
NameError: name 'random' is not defined. - Cómo solucionarlo: escribe
import randomal inicio del archivo.
2. Llamar a tu archivo random.py
- Qué ocurre: errores extraños, como
AttributeError: module 'random' has no attribute 'randint'. - Por qué ocurre: Python importa tu archivo en lugar del módulo oficial.
- Cómo solucionarlo: nunca nombres tus archivos igual que un módulo de Python. Usa, por ejemplo,
mi_dado.py.
3. Olvidar los paréntesis de random.random
- Qué ocurre:
print(random.random)muestra algo como<built-in method random ...>en lugar de un número. - Cómo solucionarlo: escribe
random.random().
🛠️ Nota técnica: los números pseudoaleatorios de
randomsirven para juegos y simulaciones, pero no para seguridad (contraseñas o códigos de acceso), porque en principio son predecibles. Para eso Python ofrece el módulosecrets. Esto será importante en el proyecto del Día 5 (generador de contraseñas).
📝 Ejercicio original del curso: Cara o Sello
Enunciado: escribe un programa que imprima al azar "Cara" o "Sello" (en el original: Heads o Tails).
Conceptos: random.randint, if/else.
🔍 Antes de programar
- ¿Cuántos resultados posibles hay? ¿Qué rango de números necesitas para representarlos?
- ¿Cómo asocias cada número con un resultado?
- ¿Cómo compruebas que el programa es "justo"? (Pista: ejecútalo muchas veces y cuenta los resultados.)
Estrategia del curso: generar 0 o 1 con randint(0, 1). Si sale 0 es "Cara"; en cualquier otro caso, "Sello".
Retos adicionales (creados para esta adaptación)
🟢 Reto 1: Aplicación
Simula el lanzamiento de dos dados y muestra la suma.
🟡 Reto 2: Ampliación
Genera una temperatura aleatoria entre 14.0 y 32.0 °C con un decimal y recomienda la ropa adecuada con if/elif/else.
🟠 Reto 3: Desafío: moneda cargada
Simula una moneda "tramposa" que sale Cara el 70 % de las veces. Usa random.random() y una comparación. Explica en un comentario por qué funciona.
🔴 Reto 4: Pensamiento computacional: adivina el número (una oportunidad)
El computador "piensa" un número del 1 al 20. El usuario tiene un intento y el programa le dice si acertó, si se quedó corto o si se pasó, y por cuántos. Diseña el diagrama de flujo antes de programar. (En el Día 12 del curso construirás la versión completa, con varios intentos.)
🧩 Comprueba lo aprendido: Tema 1
- Conceptual: ¿por qué los números del computador se llaman pseudoaleatorios?
- Predicción: ¿qué valores puede producir
random.randint(0, 2)? ¿Yint(random.random() * 3)? - Depuración:
import Randomseguido deprint(random.randint(1, 10))falla. ¿Por qué? - Creación: crea un módulo
datos_colegio.pycon el nombre de tu colegio y el año de fundación, e imprímelos desde otro archivo.
Evidencia: código del Reto 4 con su diagrama de flujo.
2. Listas: índices, modificación y append()
(Fuentes: 032 - Understanding the Offset and Appending Items to Lists.md, 033 - Who will pay the bill-.md)
Prerequisito: subíndices de strings (Día 2, Tema 1),
len()(Día 1).
🎯 Objetivo de aprendizaje
- Crear listas y acceder a sus elementos con índices positivos y negativos.
- Modificar elementos y agregar nuevos con
append()yextend(). - Combinar listas con
randompara elegir elementos al azar.
🧠 ¿Qué aprenderemos?
- ¿Qué es una estructura de datos?
- Sintaxis de las listas, índices como desplazamiento (offset).
- Modificar,
append(),extend(),random.choice().
📖 Explicación conceptual
¿Por qué listas?
Una variable guarda un dato. Pero a veces los datos van juntos y tienen un orden: la fila de la cafetería, los estudiantes de un curso, los departamentos de Colombia. Crear departamento1, departamento2, …, departamento32 sería absurdo. Una lista los guarda todos en una sola variable, en orden.
frutas = ["Cereza", "Manzana", "Pera"]- Se abre y se cierra con corchetes
[ ]. - Los elementos van separados por comas.
- Pueden ser de cualquier tipo, incluso mezclados:
["Ana", 16, 1.62, True].
Índices como desplazamiento ¿Por qué el primer elemento está en la posición 0? El curso lo explica así: el índice no es "la posición", sino cuántos pasos te alejas del inicio. El primer elemento está justo al inicio: 0 pasos.
departamentos = ["Amazonas", "Antioquia", "Arauca", "Atlántico"]
print(departamentos[0]) # Amazonas
print(departamentos[2]) # Arauca
print(departamentos[-1]) # Atlántico (el último)Modificar un elemento
departamentos[1] = "ANTIOQUIA"Agregar elementos
departamentos.append("Bolívar") # agrega UN elemento al final
departamentos.extend(["Boyacá", "Caldas"]) # agrega VARIOS (otra lista) al finalConsejo del curso: no memorices todos los métodos de las listas. Consulta la documentación oficial (se abre en otra pestaña) para saber qué existe y búscalo cuando lo necesites. Programar es un examen a libro abierto.
Elegir al azar de una lista
import random
ganador = random.choice(departamentos)🔎 Ejemplo explicado: la fila de la cafetería
fila = ["Sara", "Tomás", "Luisa"]
print(f"Primero en la fila: {fila[0]}")
fila.append("Mateo")
print(f"Acaba de llegar: {fila[-1]}")
print(f"Personas en la fila: {len(fila)}")- Qué problema resuelve: representa una fila que conserva el orden de llegada.
- Resultado esperado:
Primero en la fila: Sara,Acaba de llegar: MateoyPersonas en la fila: 4. - Observa:
len()también funciona con listas (Día 2:len()acepta secuencias).
⚠️ Errores frecuentes
1. Usar paréntesis en vez de corchetes para el índice
- Qué ocurre:
fila(0)produceTypeError: 'list' object is not callable. - Cómo solucionarlo: usa
fila[0].
2. Confundir append con extend
- Qué ocurre:
lista.append(["a", "b"])agrega una lista dentro de la lista, no dos elementos. - Cómo solucionarlo: para agregar varios elementos usa
extend.
3. Olvidar las comas entre los elementos
- Qué ocurre:
["Sara" "Tomás"]no da error, pero ¡crea un solo elemento:"SaraTomás"! Python une automáticamente dos strings escritos uno junto al otro. - Cómo identificarlo: revisa con
len()cuántos elementos tiene la lista realmente.
📝 Ejercicio original del curso: ¿Quién paga la cuenta?
Contexto del curso: en el distrito financiero de Londres, algunos grupos de banqueros deciden quién paga la cuenta de todos sacando al azar una tarjeta de presentación de un recipiente.
Enunciado: dada una lista de amigos, imprime al azar el nombre de quien paga.
Conceptos: listas, índices, random.
🔍 Antes de programar
- ¿Qué índices son válidos en una lista de 5 nombres?
- ¿Puedes resolverlo solo con lo que ya sabes (
randint+ índice)? - ¿Existirá una función hecha para esto? ¿Cómo la buscarías?
El curso presenta dos soluciones válidas:
| Opción | Idea | Ventaja |
|---|---|---|
| 1. Buscar en la documentación | random.choice(amigos) |
Menos código y más legible |
| 2. Usar lo que ya sabes | Índice aleatorio con randint y luego amigos[indice] |
Demuestra comprensión de los índices |
🛠️ Nota técnica: la solución 2 del curso usa
randint(0, 4), un número fijo que solo funciona con exactamente 5 amigos. Es más robusto escribirrandint(0, len(amigos) - 1), que se adapta a listas de cualquier tamaño.
Retos adicionales (creados para esta adaptación)
🟢 Reto 1: Aplicación
Crea una lista con 5 canciones y muestra la primera, la última y una al azar.
🟡 Reto 2: Ampliación
Pide al usuario tres nombres, uno por uno, agrégalos con append() a una lista vacía [] y muestra la lista final y su tamaño.
🟠 Reto 3: Desafío: menú del día
Con tres listas (sopas, platos fuertes y bebidas), genera al azar un menú completo. Luego permite que el usuario cambie el plato fuerte por otro al azar si escribe "otro".
🔴 Reto 4: Pensamiento computacional: orden del día
El curso tiene 6 exposiciones y el profesor quiere sortear quién expone primero y quién expone último, sin que sea la misma persona. Sin usar ciclos, ¿cómo lo garantizas? Investiga en la documentación el método remove() o random.sample(), elige una estrategia y justifícala.
🧩 Comprueba lo aprendido: Tema 2
- Conceptual: explica con tus palabras por qué el primer índice es 0.
- Predicción: con
x = [10, 20, 30, 40], ¿qué valenx[1],x[-2]ylen(x)? ¿Qué queda enxdespués dex[0] = 5yx.append(50)? - Depuración:
colores = ["rojo", "azul" "verde"]y luegoprint(colores[2])produce un error. Explica por qué. - Creación: una lista de 4 frases motivacionales y un programa que muestre una al azar cada vez que se ejecute.
Evidencia: solución de "¿Quién paga la cuenta?" con las dos estrategias.
3. IndexError y listas anidadas
(Fuente: 034 - IndexErrors and Working with Nested Lists.md)
Prerequisito: Tema 2.
🎯 Objetivo de aprendizaje
- Diagnosticar y corregir un
IndexError, incluido el error de "desfase por uno" (off-by-one). - Crear listas dentro de listas y acceder a sus elementos con dos índices.
📖 Explicación conceptual
IndexError: list index out of range
Aparece cuando pides un índice que no existe. En una lista de 50 elementos, el último está en el índice 49, no en el 50.
estados = [...] # 50 estados
numero_de_estados = len(estados) # 50
print(estados[numero_de_estados]) # ❌ IndexError
print(estados[numero_de_estados - 1]) # ✅ el últimoEste es el error de desfase por uno (off-by-one): te pasas por un solo lugar. Es de los errores más comunes de la programación.
Listas anidadas Una lista puede contener otras listas. El curso usa la "Docena Sucia" (Dirty Dozen), un listado del Environmental Working Group con las frutas y verduras que tienen más residuos de pesticidas:
frutas = ["Fresas", "Espinacas", "Kale", "Nectarinas", "Manzanas", "Uvas", "Duraznos", "Cerezas", "Peras"]
verduras = ["Tomates", "Apio", "Papas"]
docena_sucia = [frutas, verduras]
print(docena_sucia)
# [['Fresas', ..., 'Peras'], ['Tomates', 'Apio', 'Papas']]Los dos corchetes al inicio y al final muestran que es una lista de listas.
Acceder a un elemento de una lista anidada (ampliación de esta adaptación):
print(docena_sucia[1]) # ['Tomates', 'Apio', 'Papas'] → la sublista
print(docena_sucia[1][1]) # Apio → primero la sublista, luego el elementoLee docena_sucia[1][1] de izquierda a derecha: "de docena_sucia, toma el elemento 1 (verduras), y de ahí toma el elemento 1 (Apio)".
🛠️ Nota: el curso califica de "fruta" a las espinacas, el kale y otros vegetales, porque así están agrupados en la lista del ejemplo. Para programar esto no importa, pero es un buen momento para revisar críticamente cómo están clasificados los datos.
🔎 Ejemplo explicado: horario escolar
horario = [
["Matemáticas", "Español", "Inglés"], # lunes
["Tecnología", "Física", "Educación Física"], # martes
]
print(f"El martes a primera hora tienes {horario[1][0]}")- Resultado esperado:
El martes a primera hora tienes Tecnología. - Por qué es útil: los datos quedan organizados como una tabla de filas (días) y columnas (horas).
⚠️ Errores frecuentes
- Usar
len(lista)como índice →IndexError. El último índice válido eslen(lista) - 1. - Invertir el orden de los índices anidados:
horario[0][1]yhorario[1][0]son elementos distintos. - Usar un índice doble en una lista simple:
frutas[0][0]no da error, pero devuelve"F", ¡la primera letra del string! Revisa qué tipo de dato estás indexando.
Retos adicionales (creados para esta adaptación)
(El archivo 034 no propone un ejercicio propio; estos retos refuerzan sus conceptos.)
🟢 Reto 1: Aplicación
Con la docena_sucia, imprime la última fruta y la primera verdura.
🟡 Reto 2: Ampliación
Agrega una tercera sublista con granos (por ejemplo, arroz y fríjol) usando append() y muestra cuántas categorías tiene ahora la lista.
🟠 Reto 3: Desafío: el mapa del tesoro
Crea una cuadrícula de 3 × 3 con tres listas de "⬜". Pide al usuario una posición de dos dígitos (por ejemplo 21: columna 2, fila 1), marca esa casilla con "X" y muestra el mapa, una fila por línea. (Pista: posicion[0] es la columna como texto. Conviértela y réstale 1.)
🔴 Reto 4: Pensamiento computacional
Diseña una estructura de datos con listas anidadas para guardar las notas de 3 estudiantes en 3 materias. Escribe el código que imprima la nota del segundo estudiante en la tercera materia y el promedio del primer estudiante. Justifica en un comentario por qué organizaste los datos así y no al revés.
🧩 Comprueba lo aprendido: Tema 3
- Predicción: con
m = [[1, 2], [3, 4], [5, 6]], ¿qué valenm[2][0],m[-1][-1]ylen(m)? ¿Qué pasa conm[3][0]? - Depuración: el código
print(nombres[len(nombres)])debería mostrar el último nombre. Corrígelo de dos formas.
Evidencia: Reto 3 (mapa del tesoro) funcionando con al menos tres posiciones diferentes.
4. 🚀 Proyecto del día: Piedra, Papel o Tijera
(Fuente: 035 - Day 4 Project- Rock Paper Scissors.md, proyecto oficial del curso original)
Problema
Construir un juego de Piedra, Papel o Tijera en el que el usuario juega una ronda contra el computador.
Contexto
Las reglas son: la piedra le gana a la tijera, la tijera le gana al papel y el papel le gana a la piedra. Si ambos eligen lo mismo, es empate. El curso incluso cita a la World Rock Paper Scissors Association como referencia de las reglas oficiales.
Objetivo
El usuario elige escribiendo 0 (piedra), 1 (papel) o 2 (tijera). El computador elige al azar. El programa muestra las dos elecciones con arte ASCII y anuncia el resultado.
Requisitos funcionales
- Pedir la elección del usuario (0, 1 o 2), con el cursor en una línea nueva.
- Generar al azar la elección del computador.
- Mostrar ambas elecciones con su dibujo ASCII.
- Anunciar "Ganaste", "Perdiste" o "Empate".
- Si el usuario escribe un número inválido, mostrar "Escribiste un número inválido. Pierdes" sin que el programa se bloquee.
Restricciones técnicas
random, listas, if/elif/else, operadores lógicos e int(input()). El código inicial del curso trae el arte ASCII de cada figura guardado en las variables rock, paper y scissors. Ese archivo no está incluido entre los materiales suministrados, así que puedes buscar tus propios dibujos o crearlos.
🔍 Antes de programar
- Divide el problema (recomendación del curso): primero la lógica con números, después los dibujos.
- Construye la tabla de los 9 casos (3 × 3) posibles: ¿quién gana en cada uno?
- ¿Qué pasa si el usuario escribe
5, y en qué momento hay que revisarlo?
Construcción paso a paso (siguiendo la solución del curso)
Versión 1: las elecciones. Pide la elección del usuario (con int()) y genera la del computador con random.randint(0, 2). Imprime el número que eligió el computador para probar.
El curso muestra el error que aparece al olvidar
int():'>' not supported between instances of 'int' and 'str'.
Versión 2: la lógica. El curso llega a la solución por prueba y error, probando casos y agregando condiciones cuando algo falla. Estas son las condiciones a las que llega:
| Situación | Resultado |
|---|---|
| El usuario escribe un número ≥ 3 o < 0 | Número inválido, pierdes |
| Ambas elecciones son iguales | Empate |
| Usuario 0 (piedra) y computador 2 (tijera) | Ganas (excepción a la regla general) |
| Computador 0 (piedra) y usuario 2 (tijera) | Pierdes (excepción a la regla general) |
| Elección del computador > elección del usuario | Pierdes |
| Elección del usuario > elección del computador | Ganas |
Lección clave del curso sobre el ORDEN: al principio, la validación del número inválido estaba al final del
if/elif, y un número como456"ganaba" porque lo atrapaba antesusuario > computador. La validación debe ir primero.
Versión 3: los dibujos. Guarda los tres dibujos en una lista en el mismo orden que los números: imagenes = [piedra, papel, tijera]. Así imagenes[eleccion_usuario] muestra el dibujo correcto sin más if. Muestra el dibujo del usuario solo si su número es válido, porque de lo contrario se produce un IndexError.
Alternativa válida (ampliación de esta adaptación, no aparece en el curso)
Con el operador módulo del Día 3 la lógica se reduce a una sola regla:
if eleccion_usuario == eleccion_computador:
resultado = "Empate"
elif (eleccion_usuario - eleccion_computador) % 3 == 1:
resultado = "Ganaste"
else:
resultado = "Perdiste"Verifica con la tabla de 9 casos que ambas versiones dan el mismo resultado. Discute: ¿cuál es más fácil de entender? ¿Cuál es más fácil de extender a más figuras?
Pruebas
| Usuario | Computador | Resultado esperado |
|---|---|---|
| 0 | 0 | Empate |
| 0 | 2 | Ganaste |
| 2 | 0 | Perdiste |
| 1 | 0 | Ganaste |
| 1 | 2 | Perdiste |
| 7 | cualquiera | Número inválido, sin que el programa se bloquee |
| -1 | cualquiera | Número inválido (ojo: imagenes[-1] no da error, pero mostraría la tijera) |
💡 Como el computador elige al azar, para probar un caso específico puedes fijar temporalmente
eleccion_computador = 2y luego volver a la versión aleatoria.
🧪 Prueba y depuración
Este código tiene tres errores de lógica. Encuéntralos con la tabla de pruebas:
if eleccion_usuario == eleccion_computador:
print("Empate")
elif eleccion_computador > eleccion_usuario:
print("Perdiste")
elif eleccion_usuario == 0 and eleccion_computador == 2:
print("Ganaste")
elif eleccion_usuario > eleccion_computador:
print("Ganaste")
elif eleccion_usuario >= 3 or eleccion_usuario < 0:
print("Número inválido")⭐ Extensión del proyecto
- Aceptar también que el usuario escriba
"piedra","papel"o"tijera". (Investiga el métodolista.index().) - Mostrar el nombre de cada elección además del dibujo, usando una segunda lista
nombres = ["Piedra", "Papel", "Tijera"].
5. 🌟 Proyecto extra: Sorteo de la Semana de la Ciencia
Situación
En la Semana de la Ciencia, cada curso debe presentar un experimento. Para que sea justo, el docente quiere sortear el tema, el estudiante líder y el orden de presentación del curso.
Objetivo
Construir un programa de sorteo que:
- Tenga una lista de temas (por ejemplo, energía solar, reciclaje, volcanes, circuitos y fotosíntesis) y una lista con los estudiantes del grupo.
- Permita agregar un estudiante nuevo con
append()antes del sorteo. - Sortee el tema y el líder.
- Sortee un colíder que no sea el mismo líder. (Decide: ¿
remove(),random.sample()o un índice calculado?) - Muestre un "acta del sorteo" con f-strings.
Decisiones que debes tomar
- ¿Cómo evitas que el líder y el colíder sean la misma persona sin usar ciclos?
- ¿Qué pasa si la lista de estudiantes tiene una sola persona? ¿Cómo lo detectas con
len()y unif?
Casos de prueba
- Lista de 1 estudiante → mensaje: "Se necesitan al menos 2 estudiantes".
- Lista de 5 estudiantes → líder y colíder diferentes. Ejecuta 10 veces y verifica que nunca se repitan.
⭐ Extensión
Organiza los grupos de todo el grado como una lista anidada ([["10A", ...], ["10B", ...]]), sortea primero el curso y luego un estudiante de ese curso.
6. 🏆 Proyecto integrador del Día 4: Piedra, Papel, Tijera, Lagarto, Spock
Proyecto integrador creado para esta adaptación. Combina listas,
random, validación, operadores lógicos, módulo (Día 3) y f-strings (Día 2).
Situación problema
La versión "extendida" del juego, popularizada por una serie de televisión, agrega dos figuras: Lagarto y Spock. Con 5 figuras hay 25 combinaciones posibles, y resolverlas con if una por una es largo y propenso a errores.
Reglas: la tijera corta el papel, el papel cubre la piedra, la piedra aplasta al lagarto, el lagarto envenena a Spock, Spock rompe la tijera, la tijera decapita al lagarto, el lagarto se come el papel, el papel desautoriza a Spock, Spock vaporiza la piedra y la piedra aplasta la tijera.
Pregunta orientadora
¿Cómo representar las reglas de un juego de forma que el programa sea corto, correcto y fácil de verificar?
Requerimientos
- Una lista
figurascon los 5 nombres. - Pedir la elección del usuario como número (0 a 4) y validarla antes de cualquier otra cosa.
- Elegir la figura del computador con
random. - Mostrar ambas elecciones por su nombre, usando la lista.
- Determinar el resultado. Reto de diseño: si ordenas las figuras como
["Piedra", "Spock", "Papel", "Lagarto", "Tijera"], existe una regla con% 5que decide quién gana. Descúbrela en papel analizando la tabla de 25 casos. (Pista: compárala con la regla% 3del proyecto del día.) - Mostrar por qué ganó alguien. Por ejemplo: "Spock vaporiza la piedra". (Decide cómo guardar esas frases.)
Restricciones técnicas
Conceptos de los Días 1 a 4. Sin ciclos.
Etapas de desarrollo
- Tabla de 25 casos en papel.
- Descubrir y verificar la regla con
%. - Programar la validación, las elecciones y el resultado.
- Agregar las frases explicativas.
- Probar con un valor fijo del computador y luego volver al azar.
Entregables
Código funcional, tabla de 25 casos y explicación escrita de la regla con %.
Criterios técnicos
- Los 25 casos se resuelven correctamente.
- Las entradas inválidas (5, -1, 10) no bloquean el programa ni muestran una figura.
- El código usa listas en lugar de repetir
ifpor cada figura.
Posibles extensiones
Agrega dibujos ASCII o emojis para cada figura. Investiga cómo se generalizaría la regla a 7 figuras.
7. 🤖 Programar con apoyo de IA
El curso insiste en dos habilidades complementarias: buscar (como hallar random.choice en la documentación) y deducir con lo que ya sabes (como armar un índice aleatorio con randint). Una IA puede darte la primera respuesta rápido, pero la segunda habilidad es la que te permite comprobar si esa respuesta es correcta.
Actividad: auditar una solución. Pide a una IA la lógica de Piedra, Papel o Tijera. Luego:
- Pasa su código por tu tabla de 9 casos más los casos inválidos (7 y -1).
- Verifica si valida la entrada antes de usarla como índice.
- Si usa algo que no conoces (por ejemplo, diccionarios, que verás en el Día 9), búscalo en la documentación y escribe qué hace.
- Escribe un informe corto: ¿pasó todas las pruebas?, ¿qué corregiste?
8. 🛠️ Correcciones técnicas al material original
| Archivo | Afirmación en la transcripción | Qué ocurre realmente | Tratamiento |
|---|---|---|---|
031 |
"random.random() siempre incluye 1 pero puede que nunca incluya 1" (frase confusa) |
Genera valores en el rango [0, 1): incluye 0 y nunca 1 | Tabla del Tema 1 |
031 |
No advierte sobre la seguridad | random no es apto para contraseñas ni seguridad; para eso existe secrets |
Nota técnica del Tema 1 |
032 |
estado2 == "Pennsylvania" al crear variables |
Es una comparación, no una asignación (error de dictado). Lo correcto es = |
Se usa = |
033 |
randint(0, 4) con un número fijo |
Solo funciona con 5 elementos. Es mejor randint(0, len(lista) - 1) |
Nota técnica del Tema 2 |
035 |
"generar un número aleatorio entre 1 y 3" | La solución usa 0 a 2, para que coincida con los índices de la lista | Se usa 0 a 2 |
035 |
Validación con >= 3 or < 0 |
Correcta, pero imagenes[-1] no da error y mostraría la tijera; por eso la validación debe ir antes de mostrar los dibujos |
Casos de prueba del proyecto |
9. 📋 Matriz de trazabilidad
| Contenido original | Archivo de origen | Concepto desarrollado | Ejercicio original | Reto adicional | Proyecto relacionado |
|---|---|---|---|---|---|
| Objetivos: Piedra, Papel o Tijera | 030 |
Sección 0 | — | — | Sección 4 |
Aleatoriedad, random, módulos propios |
031 |
Tema 1 | Cara o Sello | Retos 1–4 del Tema 1 (dado, moneda cargada, adivinar) | Proyectos 4, 5 y 6 |
Listas, desplazamiento, modificación, append, extend |
032 |
Tema 2 | — (lección guiada) | Retos 1–4 del Tema 2 | Proyectos 4, 5 y 6 |
random.choice frente a índice aleatorio |
033 |
Tema 2 | ¿Quién paga la cuenta? (dos soluciones) | Reto 4 del Tema 2 (orden de exposición) | Proyecto 5 |
IndexError, desfase por uno, listas anidadas |
034 |
Tema 3 | — | Retos 1–4 del Tema 3 (mapa del tesoro, notas) | Proyecto 5 (extensión) |
| Piedra, Papel o Tijera | 035 |
Integración | Proyecto oficial completo | Alternativa con %, depuración y extensiones |
Sección 4 |
| Programar es como ir al gimnasio | 036 |
Sección 0 | — | — | — |
| (No existe en el curso original) | — | — | — | Sorteo de la Semana de la Ciencia | Sección 5 |
| (No existe en el curso original) | — | — | — | Piedra, Papel, Tijera, Lagarto, Spock | Sección 6 |
10. 📦 Evidencias de aprendizaje del Día 4
- Piedra, Papel o Tijera funcionando, con la tabla de 9 casos más los casos inválidos probados.
- "¿Quién paga la cuenta?" resuelto con las dos estrategias del curso.
- Mapa del tesoro (Reto 3 del Tema 3) funcionando.
- Uno de los proyectos adicionales: el Sorteo o la versión Lagarto-Spock con su tabla de 25 casos.
- Cuaderno de errores actualizado:
IndexError(desfase por uno),AttributeErrorpor llamar a un archivo igual que un módulo yTypeError: 'list' object is not callable.