Este tutorial adapta pedagógicamente el Día 21. 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.
Nota sobre las verificaciones: los ejemplos de herencia (
AnimalyFish) y de slicing se ejecutaron con Python 3.14, y los resultados que aparecen aquí son los obtenidos. También se calcularon las distancias de colisión de la serpiente. Los programas con ventana se revisaron siguiendo la lógica del código y la documentación oficial (se abre en otra pestaña). Ejecútalos en tu computador para ver el resultado.
Tabla de contenidos
- Antes de empezar
- Herencia de clases
- La comida: heredar de
Turtley detectar colisiones - El marcador: escribir texto en la pantalla
- Fin del juego: colisión con la pared
- Crecer y chocar con la cola
- Slicing: cortar listas y tuplas
- 🚀 Proyecto del día: el juego de la serpiente completo
- 🌟 Proyecto extra: el Recolector de Reciclaje
- 🏆 Proyecto integrador del Día 21: la Familia de Personajes del Videojuego
- 🧩 Comprueba lo aprendido
- 🤖 Programar con apoyo de IA
- 🛠️ Correcciones técnicas al material original
- 📋 Matriz de trazabilidad
- 📦 Evidencias de aprendizaje del Día 21
0. Antes de empezar
(Fuentes: 152 - Day 21 Goals- what we will make by the end of the day.md, 159 - Stay motivated by remembering the reason you signed up.md)
Ayer completamos los pasos 1 a 3 del juego. Hoy aprenderemos dos conceptos nuevos, herencia de clases y slicing, y con ellos terminaremos los pasos 4 a 7: comida, marcador, choque con la pared y choque con la cola.
Mensaje de cierre del curso: este curso es un maratón, no una carrera de velocidad. A partir de aquí se necesita motivación propia. Piensa en por qué quieres aprender a programar: un proyecto que quieres que exista, un mejor futuro, una carrera. Recordar esa razón te ayudará a seguir cuando las cosas se pongan difíciles.
💡 Actividad de inicio: escribe en tu cuaderno una frase: "Quiero aprender a programar porque…". Guárdala para releerla más adelante.
Prerequisito general: el juego de la serpiente del Día 20 funcionando, clases con
__init__yself(Días 16 y 17), índices negativos de listas (Día 4) y f-strings (Día 2).
1. Herencia de clases
(Fuente: 153 - Class Inheritance.md)
🎯 Objetivo de aprendizaje
- Crear una clase que herede atributos y métodos de otra.
- Ampliar un método heredado sin reescribirlo desde cero.
🧠 ¿Qué aprenderemos?
Superclase, subclase, super().__init__() y sobrescritura de métodos.
📖 Explicación conceptual
La analogía del curso: programaste un Robot Chef que sabe hornear, mezclar y medir. Ahora tu restaurante necesita un Chef Pastelero, que sabe todo lo que sabe un chef y además amasa y bate huevos. No lo construyes desde cero: tomas lo que ya sabe el chef y le agregas. Eso es la herencia.
Se hereda:
- La apariencia (atributos), como heredar los ojos de tu mamá.
- El comportamiento (métodos), como cortar tomates igual que tu papá.
Sintaxis:
class Animal: # superclase (la "clase madre")
def __init__(self):
self.num_eyes = 2
def breathe(self):
print("Inhala, exhala")
class Fish(Animal): # 1) la superclase va entre paréntesis
def __init__(self):
super().__init__() # 2) inicializa todo lo de Animal
def swim(self):
print("Moviéndose en el agua")nemo = Fish()
nemo.swim() # Moviéndose en el agua (método propio)
nemo.breathe() # Inhala, exhala (método heredado)
print(nemo.num_eyes) # 2 (atributo heredado)🔎 Ejemplo explicado: ampliar un método heredado
Un pez respira, pero bajo el agua. Queremos lo que hace breathe de Animal más algo propio:
class Fish(Animal):
def __init__(self):
super().__init__()
def breathe(self):
super().breathe() # primero, lo que hace Animal
print("haciéndolo bajo el agua") # después, lo propio del pezResultado verificado de nemo.breathe():
Inhala, exhala
haciéndolo bajo el aguaCuando una subclase define un método con el mismo nombre que uno de la superclase, lo sobrescribe. Con super().metodo() puedes reutilizar la versión original dentro de la nueva.
¿Por qué es útil? Puedes construir sobre una clase existente, tuya o de otra persona (como
Turtle), "sin reinventar la rueda".
⚠️ Errores frecuentes
| Error | Qué ocurre (verificado) | Solución |
|---|---|---|
Olvidar super().__init__() en el __init__ de la subclase |
AttributeError: 'Fish' object has no attribute 'num_eyes': el método heredado existe, pero los atributos de la superclase nunca se crearon |
Llama siempre super().__init__() al inicio del __init__ |
Escribir class Fish(Animal()): |
Se intenta heredar de un objeto, no de una clase; da error | La superclase va sin paréntesis |
| Sobrescribir un método sin querer | Se pierde el comportamiento original | Revisa los nombres de la superclase antes de crear un método |
Retos adicionales (creados para esta adaptación)
- 🟢 Reto 1 — Aplicación: crea
Bird(Animal)con un métodofly()y comprueba que también respira. - 🟡 Reto 2 — Ampliación: agrega a
Animalun parámetronameen__init__. ¿Cómo cambia la llamada asuper().__init__(...)enFish? - 🟠 Reto 3 — Desafío: crea
Estudianteconnombreypresentarse(), yMonitor(Estudiante)que, además de presentarse, diga de qué materia es monitor usandosuper().presentarse(). - 🔴 Reto 4 — Pensamiento computacional: diseña en papel una jerarquía de clases para los vehículos de tu ciudad (bicicleta, moto, bus, taxi). ¿Qué atributos y métodos van en la superclase y cuáles en cada subclase?
2. La comida: heredar de Turtle y detectar colisiones
(Fuente: 154 - Detect Collisions with Food.md)
📝 Ejercicio original del curso
Enunciado: crear food.py con una clase Food que herede de Turtle, se dibuje como un pequeño círculo azul en una posición aleatoria y se mueva a otra posición aleatoria cada vez que la serpiente la toque.
🔍 Antes de programar
- ¿Por qué heredar de
Turtleen lugar de guardar una tortuga como atributo (self.food = Turtle())? - La ventana es de 600 × 600. ¿Entre qué valores deben estar X e Y para que la comida no quede pegada a la pared?
- ¿Cómo sabes que dos tortugas "se tocan"?
Solución del curso, paso a paso
from turtle import Turtle
import random
class Food(Turtle):
def __init__(self):
super().__init__()
self.shape("circle")
self.penup()
self.shapesize(stretch_len=0.5, stretch_wid=0.5) # 20 × 20 → 10 × 10
self.color("blue")
self.speed("fastest") # para no ver la animación al moverse
self.refresh()
def refresh(self):
random_x = random.randint(-280, 280)
random_y = random.randint(-280, 280)
self.goto(random_x, random_y)Foodes una tortuga mejorada: por eso escribeself.shape(...)yself.goto(...)directamente.- PyCharm ayuda: al agregar la herencia, advierte "falta la llamada al
__init__de la superclase" y ofrece agregarla con la bombilla. - Cuidado con el nombre: el curso advierte que el método no debe llamarse
reset, porqueTurtleya tiene un métodoresety lo estarías sobrescribiendo sin querer (Tema 1).
Detectar la colisión en main.py, dentro del bucle del juego:
if snake.head.distance(food) < 15:
food.refresh()distance() es un método de Turtle que mide la distancia a unas coordenadas o a otra tortuga. La comida mide 10 × 10, así que una distancia menor que 15 indica un choque con un pequeño margen.
🛠️ Nota técnica (análisis verificado): el curso dice que 15 "funcionó después de hacer pruebas" y que se puede bajar a 10. Hay una razón matemática para no bajarlo: la cabeza de la serpiente siempre está en coordenadas múltiplos de 20, pero la comida aparece en cualquier entero. En el peor caso, la comida queda a 10 píxeles de la cuadrícula en X y en Y, y la distancia mínima posible es √(10² + 10²) ≈ 14,14. Con un umbral de 15 siempre se puede comer la comida; con 10, habría comidas imposibles de alcanzar.
Retos adicionales (creados para esta adaptación)
- 🟢 Reto 1: cambia la forma y el color de la comida.
- 🟡 Reto 2: haz que la comida aparezca solo en la cuadrícula de 20 (pista:
random.randint(-14, 14) * 20). ¿Qué umbral de distancia podrías usar ahora? - 🟠 Reto 3: evita que la comida aparezca encima del cuerpo de la serpiente:
refreshdebe recibir los segmentos y repetir el sorteo si hay choque. - 🔴 Reto 4: crea
GoldenFood(Food), una comida dorada que vale 3 puntos y cambia de lugar sola cada 5 segundos si nadie la come.
3. El marcador: escribir texto en la pantalla
(Fuente: 155 - Create a Scoreboard and Keep Score.md)
📝 Ejercicio original del curso
Enunciado: crear scoreboard.py con una clase Scoreboard que herede de Turtle, guarde el puntaje, lo muestre arriba de la pantalla y lo aumente en 1 cada vez que la serpiente come.
Método clave de la documentación:
turtle.write(arg, move=False, align="left", font=("Arial", 8, "normal"))font es una tupla: (nombre de la fuente, tamaño, estilo).
Cómo lo construye el curso (y los errores que encuentra)
self.score = 0yself.write(f"Score: {self.score}", align="center", font=("Arial", 24, "normal")).- Error 1: PyCharm advierte "se esperaba una tupla" cuando
fontse escribe como un solo string. Se corrige con paréntesis. - Error 2: el texto no se ve porque se escribe en negro sobre negro.
self.color("white")debe ir antes dewrite: cambiar el color después no modifica lo ya escrito. self.hideturtle()para que no se vea la flecha.- Error 3:
goto(0, 270)después de escribir no mueve el texto. El orden es:penup(),goto()y luegowrite(). Sinpenup(), además dibuja una línea. - Error 4: al aumentar el puntaje, los números se escriben uno encima del otro. Solución:
self.clear()antes de escribir el nuevo puntaje. - Evitar código repetido: el
writeaparecía en dos lugares, así que se creaupdate_scoreboard(). - Constantes:
ALIGNMENT = "center"yFONT = ("Courier", 24, "normal"), más "de videojuego".
Estructura final (en palabras): __init__ configura color, penup, goto, hideturtle y llama update_scoreboard(). increase_score() suma 1, llama clear() y update_scoreboard().
Lección importante: en Turtle, el orden de las instrucciones importa. Configura primero (color, posición) y escribe después.
Retos adicionales (creados para esta adaptación)
- 🟢 Reto 1: muestra también la longitud de la serpiente en el marcador.
- 🟡 Reto 2: muestra el puntaje en la esquina superior izquierda con
align="left". ¿Qué coordenadas usas? - 🟠 Reto 3: crea
LivesBoard(Scoreboard)que herede del marcador y agregue un contador de vidas. - 🔴 Reto 4: cada 5 puntos, el juego sube de nivel y la serpiente va más rápido. ¿Qué objeto debe saber el nivel? ¿Cómo se entera
main.py?
4. Fin del juego: colisión con la pared
(Fuente: 156 - Detect Collisions with the Wall.md)
📝 Ejercicio original del curso
Enunciado: terminar el juego cuando la cabeza se acerque demasiado a cualquiera de las cuatro paredes.
Razonamiento: la ventana va de −300 a 300 en ambos ejes. Se define un "cuadro límite" en ±280:
if snake.head.xcor() > 280 or snake.head.xcor() < -280 or snake.head.ycor() > 280 or snake.head.ycor() < -280:
game_is_on = False
scoreboard.game_over()El curso aclara que 280 no es un número perfecto: salió de muchas pruebas, algo muy común al programar juegos.
Problema de experiencia de usuario: si la serpiente solo se detiene, parece que el juego se congeló. Por eso se crea game_over() en Scoreboard: va a (0, 0) y escribe "GAME OVER" con la misma fuente. Como no se llama clear(), el puntaje final sigue visible arriba.
Análisis de esta adaptación: como la cabeza siempre está en múltiplos de 20,
xcor() > 280se cumple exactamente cuando la cabeza llega a 300. Es decir, la serpiente pierde cuando su cabeza queda a medio salir de la ventana.
Retos adicionales (creados para esta adaptación)
- 🟢 Reto 1: reescribe la condición con una función
fuera_de_limites(tortuga, limite)que devuelvaTrueoFalse. - 🟡 Reto 2: dibuja un borde visible en ±290 con una tortuga auxiliar, para que el jugador vea la pared.
- 🟠 Reto 3: crea un modo sin paredes: al salir por un lado, la serpiente aparece por el opuesto. ¿Qué segmentos debes mover?
- 🔴 Reto 4: agrega obstáculos (bloques grises) en posiciones fijas. Diseña cómo guardarlos y cómo detectar el choque de forma general.
5. Crecer y chocar con la cola
(Fuente: 157 - Detect Collisions with your own Tail.md)
📝 Ejercicio original del curso
Parte A — hacer crecer la serpiente. Se reorganiza Snake:
| Método | Qué hace |
|---|---|
add_segment(position) |
Crea un segmento cuadrado blanco en position y lo agrega a self.segments |
create_snake() |
Llama add_segment para cada posición inicial |
extend() |
Llama self.add_segment(self.segments[-1].position()): el nuevo segmento aparece donde está el último |
self.segments[-1]usa un índice negativo (Día 4): el último elemento de la lista.position()es un método deTurtleque devuelve las coordenadas (x, y).- En el siguiente fotograma, el nuevo segmento se queda en su lugar mientras el resto avanza, y así la serpiente crece un cuadro.
En main.py, al comer: food.refresh(), snake.extend() y scoreboard.increase_score().
Parte B — detectar el choque con la cola:
for segment in snake.segments:
if segment == snake.head:
pass
elif snake.head.distance(segment) < 10:
game_is_on = False
scoreboard.game_over()¿Por qué el if segment == snake.head: pass? El curso lo descubre al probar: sin esa condición, el juego termina de inmediato, porque la cabeza también está en la lista y su distancia a sí misma es 0.
Análisis de esta adaptación: aquí el umbral de 10 sí funciona sin problemas, porque todos los segmentos están sobre la cuadrícula de 20: la distancia entre la cabeza y otro segmento es 0 (choque) o al menos 20.
Retos adicionales (creados para esta adaptación)
- 🟢 Reto 1: haz que la serpiente crezca 2 segmentos por cada comida.
- 🟡 Reto 2: imprime en la consola cuántos segmentos tiene la serpiente al perder.
- 🟠 Reto 3: escribe
collides_with_tail()como método deSnakeque devuelvaTrueoFalse. ¿Por qué es mejor que esa lógica viva en la clase? - 🔴 Reto 4: recuerda el error del giro rápido del Día 20. Ahora que existe el choque con la cola, ¿qué consecuencia tiene para el jugador? Corrígelo en tu versión.
6. Slicing: cortar listas y tuplas
(Fuente: 158 - How to Slice Lists & Tuples in Python.md)
🎯 Objetivo de aprendizaje
- Obtener partes de una lista o tupla con la notación
[inicio:fin:paso]. - Usar slicing para simplificar el código de la serpiente.
📖 Explicación conceptual
Imagina las teclas de un piano:
piano_keys = ["a", "b", "c", "d", "e", "f", "g"]¿Cómo pensar las posiciones del corte? El curso propone imaginar que los números están entre los elementos, como las marcas de una regla:
| a | b | c | d | e | f | g |
0 1 2 3 4 5 6 7Así, [2:5] corta de la marca 2 a la marca 5 y da c, d, e.
| Código | Resultado (verificado) | Significado |
|---|---|---|
piano_keys[2:5] |
['c', 'd', 'e'] |
De la posición 2 hasta antes de la 5 |
piano_keys[2:] |
['c', 'd', 'e', 'f', 'g'] |
Desde la 2 hasta el final |
piano_keys[:5] |
['a', 'b', 'c', 'd', 'e'] |
Desde el inicio hasta antes de la 5 |
piano_keys[2:5:2] |
['c', 'e'] |
De 2 a 5, saltando de 2 en 2 |
piano_keys[::2] |
['a', 'c', 'e', 'g'] |
Todo, de 2 en 2 |
piano_keys[::-1] |
['g', 'f', 'e', 'd', 'c', 'b', 'a'] |
Todo, al revés |
También funciona con tuplas:
piano_tuple = ("do", "re", "mi", "fa", "sol", "la", "si")
print(piano_tuple[2:5]) # ('mi', 'fa', 'sol') (verificado)Relación con
range: la lógicainicio:fin:pasoes la misma que la derange(inicio, fin, paso)del Día 20: elfinno se incluye.
📝 Ejercicio original del curso: simplificar el choque con la cola
Enunciado: usar slicing para eliminar el if segment == snake.head: pass.
Solución del curso: snake.segments[1:] es toda la lista excepto la cabeza:
for segment in snake.segments[1:]:
if snake.head.distance(segment) < 10:
game_is_on = False
scoreboard.game_over()El programa funciona igual, pero el código es más corto y más claro.
⚠️ Errores frecuentes
| Error | Qué ocurre |
|---|---|
Creer que [2:5] incluye la posición 5 |
Falta un elemento. El fin nunca se incluye |
Escribir lista[1, 3] |
TypeError: la notación usa dos puntos, no comas |
| Pensar que el slice modifica la lista original | No la modifica: crea una nueva lista |
Retos adicionales (creados para esta adaptación)
- 🟢 Reto 1: con
dias = ["lun", "mar", "mié", "jue", "vie", "sáb", "dom"], obtén los días de semana, el fin de semana y los días en orden inverso. - 🟡 Reto 2: escribe
es_palindromo(palabra)con una sola línea usando[::-1]. Pruébala con "reconocer" y "oso". - 🟠 Reto 3: dada la lista de notas de un estudiante, obtén las tres últimas con índices negativos (
[-3:]). - 🔴 Reto 4: en la serpiente, ¿el primer segmento que la cabeza puede tocar de verdad es el índice 1? Piensa en la geometría: ¿podría la cabeza chocar con los segmentos 1, 2 o 3? Propón un slice más eficiente y justifícalo.
7. 🚀 Proyecto del día: el juego de la serpiente completo
(Fuentes: 152 a 158, junto con el proyecto del Día 20)
Problema
Completar el juego con los pasos 4 a 7: comida, marcador, pared y cola.
Requisitos funcionales
- Comida azul de 10 × 10 en posición aleatoria que cambia de lugar al ser comida.
- Marcador centrado arriba que aumenta en 1 con cada comida.
- La serpiente crece un segmento por comida.
- El juego termina al chocar con la pared o con la cola, mostrando "GAME OVER" y el puntaje final.
Restricciones técnicas
Tres clases en tres archivos (Snake, Food(Turtle) y Scoreboard(Turtle)), constantes para textos y fuentes, slicing para la cola.
Construcción paso a paso
| Versión | Qué se agrega | Sección |
|---|---|---|
| 1 | Food y detección con distance |
2 |
| 2 | Scoreboard con clear y update_scoreboard |
3 |
| 3 | Pared y game_over |
4 |
| 4 | extend y choque con la cola |
5 |
| Final | Simplificación con segments[1:] |
6 |
Diagrama de las clases del proyecto:
Turtle (módulo turtle)
/ \
Food Scoreboard Snake ──contiene──▶ [Turtle, Turtle, Turtle, ...]
(hereda) (hereda) (composición: TIENE tortugas, no ES una)Para analizar:
FoodyScoreboardson tortugas (herencia).Snaketiene una lista de tortugas (composición). ¿Por qué tiene sentido queSnakeno herede deTurtle?
Pruebas
| Caso | Resultado esperado |
|---|---|
| Comer una comida | La comida cambia de lugar, el puntaje sube 1 y la serpiente crece |
| Llegar al borde derecho | GAME OVER y la serpiente se detiene |
| Serpiente larga que gira en U sobre sí misma | GAME OVER |
| Iniciar el juego | No termina de inmediato (la cabeza no choca consigo misma) |
| Comida que aparece en una esquina difícil | Siempre se puede comer (umbral 15, sección 2) |
🧪 Prueba y depuración
Este scoreboard.py tiene cuatro errores. Encuéntralos y explica el síntoma de cada uno:
from turtle import Turtle
ALIGNMENT = "center"
FONT = "Courier", "24", "normal"
class Scoreboard(Turtle):
def __init__(self):
self.score = 0
self.write(f"Score: {self.score}", align=ALIGNMENT, font=FONT)
self.color("white")
self.goto(0, 270)
def increase_score(self):
self.score += 1
self.write(f"Score: {self.score}", align=ALIGNMENT, font=FONT)(Pistas: falta algo de la herencia; el orden de configuración (color y posición después de escribir); un lápiz que sigue abajo al ir a (0, 270); texto superpuesto. Preguntas extra: la línea de FONT no tiene paréntesis, ¿es una tupla de todos modos? Compruébalo con type(FONT). Y el tamaño está escrito como texto ("24"): pruébalo en tu computador; aunque funcione, ¿por qué es mejor escribir un número?)
⭐ Extensión del proyecto
- Reiniciar la partida con la tecla
"r"sin cerrar el programa. - Colores distintos para la cabeza y el cuerpo.
- Guardar el récord (¡justo lo que haremos el Día 24!).
8. 🌟 Proyecto extra: el Recolector de Reciclaje
Situación
El comité ambiental del colegio quiere un juego para la campaña de reciclaje: un camión recolector (con remolques que crecen como la serpiente) debe recoger residuos, pero solo los reciclables.
Requisitos
- Una superclase
Residuo(Turtle)con posición aleatoria,refresh()y un atributopuntos. - Tres subclases con herencia:
Plastico(Residuo): amarillo, +1 punto.Papel(Residuo): azul, +1 punto.Organico(Residuo): verde, −2 puntos y no hace crecer el camión.
- En pantalla hay siempre un residuo de cada tipo, guardados en una lista. La colisión se revisa con un solo bucle sobre la lista.
- El marcador muestra puntos y kilos reciclados (1 kg por residuo reciclable).
- Pierdes al chocar con la pared, con los remolques o al llegar a −5 puntos.
Decisiones que debes tomar
- ¿Qué método sobrescribe cada subclase y cuál hereda sin cambios?
- ¿Cómo evitas preguntar
if tipo == "plastico"enmain.py? (Pista: que cada residuo sepa sus puntos y si hace crecer al camión.)
Reflexión
¿Cuántas líneas te ahorró la herencia? ¿Qué pasaría si mañana hay que agregar "Vidrio"?
9. 🏆 Proyecto integrador del Día 21: la Familia de Personajes del Videojuego
Proyecto integrador creado para esta adaptación. Integra herencia, sobrescritura con
super(), composición, slicing, colisiones, marcador y eventos (Días 19 a 21).
Situación problema
El club de programación diseña un videojuego de laberinto. Necesita una familia de personajes que compartan comportamiento y se diferencien en lo que cada uno sabe hacer.
Pregunta orientadora
¿Cómo usar la herencia para agregar nuevos personajes sin modificar el código de los que ya existen?
Requerimientos
Personaje(Turtle): posición, velocidad,mover()ychoca_con(otro).Jugador(Personaje): controlado con las flechas, con vidas.Enemigo(Personaje): se mueve solo en una dirección y rebota en las paredes. Sobrescribemover()usandosuper().mover().EnemigoPerseguidor(Enemigo): sobrescribemover()para orientarse hacia el jugador contowards().Moneda(Turtle): al tocarla, suma puntos y cambia de lugar.- Un
Marcador(Turtle)con puntos, vidas y "GAME OVER". - Un historial de las últimas 5 posiciones del jugador (usa slicing para quedarte solo con ellas) y muéstralo al perder una vida.
Etapas de desarrollo
- Diagrama de clases en papel (qué hereda de qué y qué métodos se sobrescriben).
PersonajeyJugador.- Enemigos y colisiones.
- Monedas, marcador y vidas.
- Historial con slicing.
Entregables
- Código en varios archivos, uno por clase.
- Diagrama de herencia con los métodos sobrescritos marcados.
- Explicación de por qué
EnemigoPerseguidorno necesitó copiar código deEnemigo.
Casos de prueba
| Caso | Esperado |
|---|---|
| El jugador toca una moneda | Suma puntos y la moneda cambia de lugar |
| Un enemigo toca la pared | Rebota |
| El jugador pierde las 3 vidas | GAME OVER con el puntaje |
| Se agrega una nueva subclase de enemigo | main.py solo cambia en la línea que la crea |
Criterios técnicos
- Cada subclase llama
super().__init__(). - Ningún método se copia y pega entre clases.
- Las constantes (tamaños, velocidades, textos) están en mayúsculas al inicio de cada archivo.
10. 🧩 Comprueba lo aprendido
Conceptuales
- ¿Qué diferencia hay entre heredar de
Turtley tener una tortuga como atributo? - ¿Para qué sirve
super()? - ¿Por qué el marcador necesita
clear()antes de escribir?
Análisis de código
class A:
def hola(self):
return "A"
class B(A):
def hola(self):
return super().hola() + "B"
class C(B):
def hola(self):
return super().hola() + "C"
print(C().hola())¿Qué imprime? Explica el recorrido.
Predicción
n = [10, 20, 30, 40, 50, 60]
print(n[1:4], n[::3], n[-2:], n[4:1:-1])Depuración
class Food(Turtle):
def __init__(self):
self.shape("circle")
super().__init__()¿Qué problema tiene el orden de estas líneas?
Modificación
Cambia el choque con la pared para que la serpiente pierda solo si sale más allá de ±300. ¿Qué ves en pantalla antes del GAME OVER?
Creación
Crea Temporizador(Turtle) que muestre en la esquina los segundos que lleva la partida, actualizándose en cada fotograma sin superponer el texto.
11. 🤖 Programar con apoyo de IA
Actividad: la IA frente a la herencia.
- Pide a una IA que cree la clase
Foodheredando deTurtle. - Revisa: ¿llama
super().__init__()? ¿Usa algún nombre de método que ya exista enTurtle(comoreset,clearowrite) y lo sobrescribe sin querer? Busca la lista de métodos en la documentación oficial (se abre en otra pestaña). - Pregúntale qué umbral de distancia usar para detectar la comida y por qué. Compara su respuesta con el análisis de la sección 2 (√200 ≈ 14,14). ¿Te dio una razón o solo un número?
- Escribe en tu cuaderno qué parte de su respuesta verificaste y cómo.
12. 🛠️ Correcciones técnicas al material original
| Archivo | Afirmación o comportamiento del curso | Observación | Tratamiento |
|---|---|---|---|
154 |
El umbral de 15 se eligió por pruebas y puede bajarse a 10 | Con comida en cualquier entero y la cabeza en múltiplos de 20, la distancia mínima puede ser 14,14; con 10 habría comidas inalcanzables (cálculo verificado) | Nota técnica del Tema 2 |
154 |
La comida aparece en cualquier lugar | Puede aparecer encima del cuerpo de la serpiente | Reto 3 del Tema 2 |
157 |
El choque con la cola funciona con las condiciones de dirección del Día 20 | El error del giro rápido del Día 20 ahora provoca un GAME OVER injusto | Reto 4 del Tema 5 |
158 |
El slice de la tupla da "mi, fa, …" (la transcripción está incompleta) | El resultado completo es ('mi', 'fa', 'sol') (verificado) |
Tema 6 |
13. 📋 Matriz de trazabilidad
| Contenido original | Archivo de origen | Concepto desarrollado | Ejercicio original | Reto adicional | Proyecto relacionado |
|---|---|---|---|---|---|
| Objetivos del día | 152 |
Sección 0 | — | — | Sección 7 |
Herencia, super(), sobrescritura (Animal, Fish) |
153 |
Tema 1 | Fish(Animal) con breathe |
Retos 1–4 del Tema 1 | Secciones 8 y 9 |
Food(Turtle), shapesize, distance, refresh |
154 |
Tema 2 | Clase Food y colisión |
Retos 1–4 del Tema 2 | Secciones 7, 8 y 9 |
Scoreboard(Turtle), write, clear, constantes |
155 |
Tema 3 | Marcador | Retos 1–4 del Tema 3 y depuración | Secciones 7, 8 y 9 |
Colisión con la pared, game_over |
156 |
Tema 4 | Límites en ±280 | Retos 1–4 del Tema 4 | Secciones 7 y 8 |
extend, add_segment, colisión con la cola |
157 |
Tema 5 | Crecer y chocar con la cola | Retos 1–4 del Tema 5 | Secciones 7 y 8 |
| Slicing de listas y tuplas | 158 |
Tema 6 | segments[1:] |
Retos 1–4 del Tema 6 | Secciones 7 y 9 |
| Motivación: el maratón | 159 |
Sección 0 | — | Actividad de inicio | — |
| (No existe en el curso original) | — | — | — | Recolector de Reciclaje | Sección 8 |
| (No existe en el curso original) | — | — | — | Familia de Personajes | Sección 9 |
14. 📦 Evidencias de aprendizaje del Día 21
- Juego de la serpiente completo, con captura de un GAME OVER y tu puntaje.
- Diagrama de clases del proyecto que diferencie herencia y composición.
- Explicación escrita del umbral de 15 píxeles (√200).
- Los resultados de los retos de slicing del Tema 6.
- Proyecto extra (Recolector de Reciclaje) o integrador (Familia de Personajes).
- La frase "Quiero aprender a programar porque…".
- Cuaderno de errores:
super().__init__()olvidado, texto negro sobre fondo negro, texto superpuesto sinclear(),fontque no es una tupla, GAME OVER inmediato por la cabeza y el métodoresetsobrescrito.