Saltar al contenido
Inicio 100 Días de Código en Python — Día 20: El Juego de la Serpiente (Parte 1) — Animación y Coordenadas

100 Días de Código en Python — Día 20: El Juego de la Serpiente (Parte 1) — Animación y Coordenadas

Nivel: Grado décimo Área: Tecnología e Informática Modalidad: Tutorial práctico Fuente: Curso "100 Days of Code: The Complete Python Pro Bootcamp" (Angela Yu, App Brewery). Contenido del Día 20 (nivel intermedio).

Este tutorial adapta pedagógicamente el Día 20. 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: el algoritmo de movimiento de la serpiente se probó sin ventana gráfica, con segmentos simulados que imitan los métodos goto, xcor, ycor, heading y forward de Turtle. También se verificaron el error de range con argumentos de palabra clave y el comportamiento de range con paso negativo (Python 3.14). 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

  1. Antes de empezar: dividir un problema grande
  2. Configurar la pantalla y crear el cuerpo de la serpiente
  3. Animación: tracer, update y sleep
  4. El algoritmo del movimiento: la cola sigue a la cabeza
  5. Refactorizar: la clase Snake
  6. Controlar la serpiente con el teclado
  7. 🚀 Proyecto del día: la serpiente que se mueve y obedece
  8. 🌟 Proyecto extra: el Tren de la Ruta Escolar
  9. 🏆 Proyecto integrador del Día 20: Duelo de Serpientes
  10. 🧩 Comprueba lo aprendido
  11. 🤖 Programar con apoyo de IA
  12. 🛠️ Correcciones técnicas al material original
  13. 📋 Matriz de trazabilidad
  14. 📦 Evidencias de aprendizaje del Día 20

0. Antes de empezar: dividir un problema grande

(Fuentes: 146 - Day 20 Goals- what we will make by the end of the day.md, 151 - Programming is not Memorising.md)

Durante dos días construiremos el clásico juego de la serpiente, famoso en los celulares Nokia de finales de los noventa: una serpiente que se mueve sola, se controla con las flechas, come comida y crece. Pierdes si chocas con la pared o con tu propia cola.

Lo primero es descomponer el problema. El curso lo divide en siete pasos:

Día Paso Tarea
20 1 Crear el cuerpo de la serpiente (3 cuadrados)
20 2 Mover la serpiente continuamente hacia adelante
20 3 Controlar la serpiente con el teclado
21 4 Detectar la colisión con la comida
21 5 Crear un marcador de puntaje
21 6 Detectar la colisión con la pared
21 7 Detectar la colisión con la cola

Esta forma de trabajar es pensamiento computacional: un problema que parece enorme se vuelve manejable cuando se divide en partes pequeñas que se pueden probar por separado.

Mensaje de cierre del curso (día 20, ¡una quinta parte del camino!): programar no es memorizar. Es como las combinaciones de botones de un videojuego: si pasa un mes, se olvidan. Hoy la información está a una búsqueda de distancia. Tu trabajo es entender cómo funcionan las cosas, cuándo usarlas y qué pasa por dentro; la sintaxis se puede buscar y, al verla, la recordarás.

Prerequisito general: tuplas (Día 18), eventos y onkey (Día 19), coordenadas y goto (Día 19), clases con __init__ y self (Días 16 y 17), listas e índices (Día 4) y constantes en mayúsculas (Día 12).


1. Configurar la pantalla y crear el cuerpo de la serpiente

(Fuente: 147 - Screen Setup and Creating a Snake Body.md)

🎯 Objetivo de aprendizaje

  • Configurar el tamaño, el color de fondo y el título de la ventana.
  • Crear varios objetos a partir de una lista de tuplas de posiciones.

📖 Explicación conceptual

Python
from turtle import Screen, Turtle

screen = Screen()
screen.setup(width=600, height=600)   # palabras clave: más claro para quien lea
screen.bgcolor("black")               # color de fondo
screen.title("My Snake Game")         # texto de la barra de título

screen.exitonclick()

Cada segmento de la serpiente será una tortuga con forma de cuadrado. Una tortuga cuadrada mide 20 × 20 píxeles, así que, para que los cuadrados queden pegados sin superponerse, cada uno debe estar 20 píxeles a la izquierda del anterior: (0, 0), (−20, 0) y (−40, 0).

📝 Ejercicio original del curso: tres segmentos alineados

Enunciado: crear tres cuadrados blancos, alineados en el eje horizontal, sin huecos ni superposición, con el primero en (0, 0).

🔍 Antes de programar

  • Si la ventana es negra y la tortuga es negra, ¿la verás?
  • ¿Qué pasa si creas los tres cuadrados sin moverlos?
  • ¿Cómo evitas escribir tres veces el mismo código?

Solución del curso, en dos versiones:

  1. Versión repetitiva: segment_1, segment_2 y segment_3, cada uno con Turtle("square"), color("white") y un goto distinto.
  2. Versión con bucle (la recomendada):
Python
STARTING_POSITIONS = [(0, 0), (-20, 0), (-40, 0)]   # lista de tuplas (x, y)

for position in STARTING_POSITIONS:
    new_segment = Turtle("square")
    new_segment.color("white")
    new_segment.goto(position)       # goto acepta directamente una tupla

Buena práctica: la segunda versión evita el código repetido. Si mañana quieres una serpiente de 5 segmentos, solo agregas dos tuplas.

Retos adicionales (creados para esta adaptación)

  • 🟢 Reto 1: crea una serpiente de 5 segmentos agregando posiciones a la lista.
  • 🟡 Reto 2: genera la lista de posiciones con un bucle a partir de una constante STARTING_LENGTH = 5, en lugar de escribirla a mano.
  • 🟠 Reto 3: haz que la serpiente empiece vertical, con la cabeza arriba. ¿Qué coordenada cambia?
  • 🔴 Reto 4: colorea la cabeza de un color distinto al del cuerpo. ¿Dónde tomas esa decisión dentro del bucle?

2. Animación: tracer, update y sleep

(Fuente: 148 - Animating the Snake Segments on Screen.md)

🎯 Objetivo de aprendizaje

  • Controlar cuándo se redibuja la pantalla para crear una animación fluida.
  • Controlar la velocidad del juego con time.sleep.

📖 Explicación conceptual

El problema: al mover los segmentos uno por uno, se ve cómo avanza cada pieza por separado, como una oruga extraña. Además, al crear cada segmento se ve cómo nace en el centro y luego salta a su posición.

La idea de la animación. Los antiguos televisores de tubo (CRT) pintaban la imagen línea por línea y, al terminar, empezaban la siguiente. Un GIF animado es una serie de imágenes que se muestran muy rápido. En nuestro juego haremos lo mismo: preparar cada "fotograma" moviendo todas las piezas sin mostrarlas, y luego mostrarlo completo.

Herramienta Qué hace
screen.tracer(0) Apaga la animación automática: Turtle ya no redibuja después de cada movimiento
screen.update() Redibuja la pantalla en ese momento, mostrando todos los cambios pendientes
time.sleep(0.1) Pausa el programa 0,1 segundos. Controla la velocidad del juego

🔎 Ejemplo explicado: el experimento del curso

El curso mueve de lugar update() y sleep() para ver qué cambia:

Python
import time

screen.tracer(0)
# ... crear los segmentos ...

game_is_on = True
while game_is_on:
    screen.update()          # 1) muestra el fotograma completo
    time.sleep(0.1)          # 2) espera un momento
    for seg in segments:     # 3) prepara el siguiente fotograma
        seg.forward(20)
Dónde está update() Qué se ve
Nunca se llama Pantalla negra: nada aparece
Después de crear los segmentos La serpiente aparece completa de una vez
Dentro del for (después de cada segmento) Las piezas avanzan una por una
Fuera del for (una vez por vuelta) La serpiente avanza como una sola pieza ✅

Con sleep(1) se ve muy lento; con sleep(0.1) la velocidad es razonable.

⚠️ Errores frecuentes

Error Qué ocurre Solución
tracer(0) sin ningún update() Pantalla negra, parece que el programa no funciona Llama update() en cada vuelta del bucle del juego
Olvidar import time NameError: name 'time' is not defined Importa el módulo al inicio
Cerrar la ventana con el bucle activo Mensajes rojos en la consola (Terminator, TclError) Es normal por ahora, porque el bucle while no tiene salida. El curso lo aclara: lo importante es que el juego funcione

Retos adicionales (creados para esta adaptación)

  • 🟢 Reto 1: prueba sleep con 0.5, 0.1 y 0.05. ¿Cuál te parece jugable?
  • 🟡 Reto 2: crea una constante GAME_SPEED y úsala en sleep.
  • 🟠 Reto 3: anima una pelota que rebote dentro de la ventana usando tracer(0) y update().
  • 🔴 Reto 4: mide con time.time() cuántos fotogramas por segundo (FPS) logra tu juego con sleep(0.1). ¿Es exactamente 10? Explica la diferencia.

3. El algoritmo del movimiento: la cola sigue a la cabeza

(Fuente: 148 - Animating the Snake Segments on Screen.md)

🎯 Objetivo de aprendizaje

  • Explicar por qué "mover todos hacia adelante" falla al girar.
  • Implementar el algoritmo en el que cada segmento ocupa el lugar del anterior, usando range con paso negativo.

📖 Explicación conceptual

El problema al girar. Si todos los segmentos hacen forward(20) y la cabeza gira a la izquierda, solo la cabeza cambia de rumbo: el cuerpo sigue derecho y se separa. El curso lo demuestra haciendo girar la cabeza 90° en cada vuelta: la cabeza da vueltas sola y el cuerpo se va.

La solución: mover de atrás hacia adelante.

  1. El último segmento va a la posición del penúltimo.
  2. El penúltimo va a la posición del anterior… y así hasta el segundo.
  3. Por último, la cabeza avanza 20 pasos en su dirección.

Así, el cuerpo siempre recorre el mismo camino que hizo la cabeza. Es como una fila de estudiantes caminando: cada uno pisa donde estaba el de adelante.

range con tres argumentos: inicio, parada y paso.

Python
list(range(1, 4, 1))     # [1, 2, 3]
list(range(3, 0, -1))    # [3, 2, 1]  → paso negativo: cuenta hacia atrás
list(range(2, 0, -1))    # [2, 1]     → la parada (0) NO se incluye

🔎 Ejemplo explicado

Python
for seg_num in range(len(segments) - 1, 0, -1):
    new_x = segments[seg_num - 1].xcor()
    new_y = segments[seg_num - 1].ycor()
    segments[seg_num].goto(new_x, new_y)
segments[0].forward(20)
  • Con 3 segmentos, range(2, 0, -1) da 2, 1: se mueven el último y el del medio. El segmento 0 (la cabeza) no entra en el bucle porque se mueve con forward.
  • Se usa len(segments) - 1 en lugar de 2 para que el código funcione con cualquier longitud (¡la serpiente crecerá mañana!).

Verificación sin ventana (serpiente en (0, 0), (−20, 0), (−40, 0) mirando al Este): después de una vuelta, las posiciones son (20, 0), (0, 0), (−20, 0). Cada segmento ocupó el lugar del anterior y la cabeza avanzó 20.

🛠️ Nota técnica (verificada): el curso escribe primero range(start=2, stop=0, step=-1) para visualizarlo, y muestra que produce un error. Efectivamente: TypeError: range() takes no keyword arguments. El curso lo explica diciendo que range "viene del lenguaje C". Es más preciso decir que, en CPython, range está implementado en C y fue definido sin admitir argumentos por nombre. La idea práctica es la misma: con range, solo argumentos posicionales.

⚠️ Errores frecuentes

Error Qué ocurre Por qué
Recorrer de adelante hacia atrás (range(1, len)) Todos los segmentos terminan en el mismo lugar Cada uno copia una posición que ya se actualizó
Olvidar segments[0].forward(20) Los tres segmentos se apilan en la posición de la cabeza Nadie avanza: todos copian una posición que no cambia
range(len(segments), 0, -1) IndexError: list index out of range El último índice es len - 1

Retos adicionales (creados para esta adaptación)

  • 🟢 Reto 1: en papel cuadriculado, dibuja 4 vueltas del algoritmo con una serpiente de 4 segmentos que gira hacia arriba en la segunda vuelta.
  • 🟡 Reto 2: escribe el algoritmo usando solo listas de tuplas, sin Turtle, e imprime las posiciones en cada vuelta.
  • 🟠 Reto 3: reescribe el bucle recorriendo segments[::-1]... ¿funciona igual? *(Mañana veremos el *slicing. Analiza qué problema aparece con la cabeza.)
  • 🔴 Reto 4: existe otra forma de mover la serpiente: mover el último segmento al frente de la cabeza en cada vuelta. Explica cómo funcionaría y qué ventajas tendría con una serpiente de 500 segmentos.

4. Refactorizar: la clase Snake

(Fuente: 149 - Create a Snake Class & Move to OOP.md)

🎯 Objetivo de aprendizaje

  • Refactorizar: reorganizar el código sin cambiar lo que hace.
  • Crear una clase en su propio archivo con atributos, métodos y constantes.

📝 Ejercicio original del curso

Enunciado: llevar todo lo relacionado con la serpiente a un archivo snake.py con una clase Snake, de modo que main.py quede así de simple:

Python
from snake import Snake

snake = Snake()          # crea la serpiente de 3 segmentos

while game_is_on:
    screen.update()
    time.sleep(0.1)
    snake.move()         # toda la lógica del movimiento está en la clase

Resultado esperado: el programa funciona exactamente igual que antes. Solo cambia la organización.

Estructura de la solución del curso:

Elemento Contenido
Constantes arriba del archivo STARTING_POSITIONS y MOVE_DISTANCE = 20
__init__(self) Crea self.segments = [] y llama a self.create_snake()
create_snake(self) El bucle de la sección 1, con self.segments.append(new_segment)
move(self) El algoritmo de la sección 3, con self.segments

¿Por qué constantes? Si quieres cambiar dónde empieza la serpiente o cuánto avanza, miras arriba del archivo y no tienes que buscar dentro del código.

¿Por qué una clase por archivo? Al final del proyecto habrá tres clases: Snake, Food y Scoreboard. Si algo falla con la serpiente, sabes qué archivo revisar.

⚠️ Errores frecuentes

Error Mensaje Solución
Olvidar self. en segments NameError: name 'segments' is not defined Usa self.segments
No importar Turtle en snake.py NameError: name 'Turtle' is not defined Cada archivo importa lo que usa
Definir un método sin self TypeError: move() takes 0 positional arguments but 1 was given El primer parámetro de un método es self

Retos adicionales (creados para esta adaptación)

  • 🟢 Reto 1: agrega a __init__ un parámetro color para crear serpientes de distintos colores.
  • 🟡 Reto 2: agrega un método length() que devuelva el número de segmentos.
  • 🟠 Reto 3: crea dos serpientes en main.py y haz que ambas se muevan. ¿Qué pasa con sus posiciones iniciales? Agrega un parámetro para evitarlo.
  • 🔴 Reto 4: escribe los docstrings de la clase y de cada método, explicando qué hace cada uno sin mirar el código de ejemplo.

5. Controlar la serpiente con el teclado

(Fuente: 150 - How to Control the Snake with a Keypress.md)

🎯 Objetivo de aprendizaje

  • Vincular las flechas del teclado con métodos de un objeto.
  • Impedir que la serpiente se devuelva sobre sí misma.

📝 Ejercicio original del curso

Enunciado: en main.py ya están los vínculos:

Python
screen.listen()
screen.onkey(snake.up, "Up")        # método del objeto, sin paréntesis
screen.onkey(snake.down, "Down")
screen.onkey(snake.left, "Left")
screen.onkey(snake.right, "Right")

Tu trabajo: escribir los métodos up, down, left y right en la clase Snake.

Recordatorio de rumbos (sentido antihorario desde el Este):

Dirección Rumbo
Derecha (Este) 0
Arriba (Norte) 90
Izquierda (Oeste) 180
Abajo (Sur) 270

Pasos de la solución del curso:

  1. Solo se gira la cabeza (self.segments[0].setheading(90)); el cuerpo la sigue gracias al algoritmo de la sección 3.
  2. Mientras se prueba un método, los demás se dejan con pass, porque Python no acepta funciones vacías.
  3. Como la cabeza se usa en muchos lugares, se crea el atributo self.head = self.segments[0]. Cuidado: debe ir después de create_snake(); antes, la lista está vacía y daría IndexError.
  4. Se crean las constantes UP = 90, DOWN = 270, LEFT = 180, RIGHT = 0.
  5. La serpiente no puede devolverse: si va hacia abajo, no puede subir.
Python
def up(self):
    if self.head.heading() != DOWN:     # heading() es un MÉTODO: lleva paréntesis
        self.head.setheading(UP)

Con la misma lógica se completan down (si no va hacia arriba), left (si no va a la derecha) y right (si no va a la izquierda).

⚠️ Errores frecuentes

Error Qué ocurre Solución
self.head.heading sin paréntesis La condición compara un método con un número: siempre es distinta y la serpiente puede devolverse Escribe heading()
onkey(snake.up(), "Up") La serpiente gira una vez al iniciar y la tecla no responde Pasa el método sin paréntesis (Día 19)
self.head = self.segments[0] antes de create_snake() IndexError Cambia el orden de las líneas

6. 🚀 Proyecto del día: la serpiente que se mueve y obedece

(Fuentes: 146 a 150)

Problema

Construir la primera mitad del juego de la serpiente: pasos 1, 2 y 3.

Contexto

Recrear un clásico es una excelente forma de aprender: sabes exactamente cómo debe comportarse, así que puedes comprobar si tu programa lo hace bien.

Requisitos funcionales

  1. Ventana negra de 600 × 600 con título.
  2. Serpiente blanca de 3 segmentos en el centro.
  3. Movimiento continuo y fluido, como una sola pieza.
  4. El cuerpo sigue el camino de la cabeza al girar.
  5. Control con las flechas, sin poder devolverse.

Restricciones técnicas

Clase Snake en snake.py, constantes, tracer(0) y update(), time.sleep y range con paso negativo.

Planificación y construcción

Versión Qué se agrega Sección
1 Pantalla y cuerpo con lista de tuplas 1
2 Bucle del juego con tracer, update y sleep 2
3 Algoritmo "la cola sigue a la cabeza" 3
4 Clase Snake en su archivo 4
Final Control con teclado y prohibición de devolverse 5

Después de cada versión, ejecuta y comprueba que todo lo anterior sigue funcionando. Eso es lo que hace el curso en cada lección.

Pruebas

Caso Resultado esperado
Iniciar el juego La serpiente aparece completa (no pieza por pieza) y avanza a la derecha
Pulsar ↑ Gira hacia arriba y el cuerpo dobla la esquina siguiendo a la cabeza
Yendo a la derecha, pulsar ← No pasa nada
Pulsar ↑, ←, ↓, → con pausas Dibuja un cuadrado

🧪 Prueba y depuración: el giro demasiado rápido

Hay un error que el curso no detecta. Imagina que la serpiente va a la derecha y el jugador pulsa ↑ y ← muy rápido, antes de que se dibuje el siguiente fotograma:

  1. up(): el rumbo actual es 0 (no es abajo) → la cabeza cambia a 90.
  2. left(): el rumbo actual ahora es 90 (no es derecha) → la cabeza cambia a 180.
  3. En el siguiente fotograma, la cabeza avanza a la izquierda… ¡sobre su propio cuerpo!

Verificación sin ventana: con la serpiente en (20, 0), (0, 0), (−20, 0) mirando al Este, aplicar up() y left() seguidos y luego move() deja la cabeza en (0, 0), exactamente donde queda el segundo segmento. Mañana, cuando se detecte el choque con la cola, esto hará perder al jugador sin que haya hecho nada prohibido.

Actividad:

  • Explica con tus palabras por qué la condición if self.head.heading() != DOWN no es suficiente.
  • Propón una corrección. (Idea: guardar la "dirección solicitada" en un atributo y aplicarla dentro de move(), comparándola con la dirección en la que la serpiente realmente se movió en el último fotograma.)

⭐ Extensión del proyecto

  • Aceptar también las teclas W, A, S y D.
  • Una tecla "p" para pausar y reanudar (pista: una variable que controle si move() se ejecuta).
  • Que la serpiente acelere un poco cada 10 segundos.

7. 🌟 Proyecto extra: el Tren de la Ruta Escolar

Situación

La coordinación del colegio quiere una animación para la pantalla de la entrada: un tren de vagones que recorre el mapa del colegio y se detiene en cada parada (portería, biblioteca, cafetería, laboratorio, coliseo).

Requisitos

  1. Un mapa simple dibujado con Turtle y las paradas marcadas con dot y su nombre con write.
  2. Una lista de tuplas RUTA con las coordenadas de cada parada.
  3. Una clase Tren con una locomotora y 4 vagones que siguen a la locomotora con el algoritmo de la sección 3.
  4. La locomotora usa towards(x, y) (búscalo en la documentación) para orientarse hacia la siguiente parada y avanza de 10 en 10 hasta llegar a ella.
  5. En cada parada, el tren se detiene 1 segundo y la consola muestra "Llegando a: ...".
  6. Al terminar la ruta, vuelve a empezar.

Decisiones que debes tomar

  • ¿Cómo sabes que la locomotora "llegó" si no cae exactamente en la coordenada? (Pista: distance() y un margen.)
  • ¿Qué atributo guarda a qué parada se dirige el tren?

Reflexión

¿Qué partes de la clase Snake pudiste reutilizar? ¿Qué tuviste que cambiar porque el tren no lo controla una persona?


8. 🏆 Proyecto integrador del Día 20: Duelo de Serpientes

Proyecto integrador creado para esta adaptación. Integra instancias y estado (Día 19), eventos (Día 19), animación y el algoritmo de movimiento (Día 20), y clases con parámetros (Días 16 y 17).

Situación problema

Para el torneo de videojuegos del descanso, se quiere un juego de serpientes para dos jugadores en el mismo teclado.

Pregunta orientadora

¿Cómo reutilizar una sola clase para crear dos objetos con estado distinto que respondan a controles distintos?

Requerimientos

  1. La clase Snake recibe como parámetros el color, la posición inicial y el rumbo inicial.
  2. Jugador 1: serpiente verde a la izquierda, controles W, A, S, D. Jugador 2: serpiente azul a la derecha, controles con las flechas.
  3. Ninguna serpiente puede devolverse, incluido el caso del giro rápido de la sección 6.
  4. Una tecla "space" inicia la partida; antes, las serpientes están quietas.
  5. Constantes para el tamaño de la ventana, la velocidad y la distancia de movimiento.

Etapas de desarrollo

  1. Clase Snake parametrizada y dos instancias en pantalla.
  2. Movimiento de ambas en el mismo bucle.
  3. Controles separados.
  4. Corrección del giro rápido y tecla de inicio.

Entregables

  • snake.py y main.py.
  • Un diagrama que muestre las dos instancias, sus atributos y qué teclas llaman a qué métodos.
  • Un video corto o capturas de una partida.

Casos de prueba

Caso Esperado
Pulsar W Solo gira la serpiente verde
Pulsar ↑ Solo gira la serpiente azul
Pulsar dos teclas rápido en un mismo fotograma Ninguna serpiente se devuelve sobre sí misma
Antes de pulsar espacio Nada se mueve

Criterios técnicos

  • main.py no contiene lógica de movimiento: solo crea objetos, vincula teclas y ejecuta el bucle.
  • Agregar un tercer jugador solo requiere crear otra instancia y sus vínculos.

Posibles extensiones

Mañana, al aprender las colisiones, podrás hacer que pierda la serpiente que choque con la otra.


9. 🧩 Comprueba lo aprendido

Conceptuales

  1. ¿Para qué sirven tracer(0) y update()? ¿Qué pasa si usas solo uno de los dos?
  2. ¿Por qué el bucle del movimiento recorre los segmentos de atrás hacia adelante?
  3. ¿Qué significa refactorizar? ¿Cómo sabes que una refactorización salió bien?

Análisis de código

Python
print(list(range(5, 0, -2)))
print(list(range(0, 5, -1)))

Explica cada resultado.

Predicción

Serpiente en (0, 0), (−20, 0), (−40, 0) mirando al Este. Se pulsa ↑ y luego se ejecuta move() dos veces. ¿Dónde queda cada segmento?

Depuración

Python
class Snake:
    def __init__(self):
        self.head = self.segments[0]
        self.segments = []
        self.create_snake()

    def up(self):
        if self.head.heading != 270:
            self.head.setheading(90)

Encuentra dos errores y explica qué síntoma produciría cada uno.

Modificación

Cambia MOVE_DISTANCE a 10. ¿Qué otro valor del código también deberías cambiar para que los segmentos no se superpongan?

Creación

Escribe un programa que anime un reloj: una tortuga-manecilla que gira 6° por segundo usando tracer(0), update() y sleep(1).


10. 🤖 Programar con apoyo de IA

El mensaje del curso hoy es claro: no memorices, entiende. La IA puede darte la sintaxis que olvidaste, pero entender por qué funciona es tu trabajo.

Actividad: explicar antes de aceptar.

  1. Pide a una IA "el código del juego de la serpiente con Turtle".
  2. Antes de ejecutarlo, explica por escrito qué hace cada método. Si no puedes explicar una línea, investígala en la documentación.
  3. Revisa: ¿usa tracer(0) y update()? ¿Mueve los segmentos de atrás hacia adelante? ¿Tiene el error del giro rápido?
  4. Pregúntale directamente por el error del giro rápido. ¿Lo reconoce? ¿Su corrección funciona? Pruébala con la simulación de la sección 6.

11. 🛠️ Correcciones técnicas al material original

Archivo Afirmación o comportamiento del curso Observación Tratamiento
148 range no acepta palabras clave "porque viene del lenguaje C" El error es real (TypeError: range() takes no keyword arguments, verificado); la explicación precisa es que en CPython está implementado en C sin admitir argumentos por nombre Nota técnica del Tema 3
150 Condiciones if self.head.heading() != DOWN impiden devolverse Dos teclas pulsadas dentro del mismo fotograma permiten devolverse (verificado con simulación) Sección 🧪 del proyecto
149 Mensajes rojos al detener el programa "son normales" Correcto en esta etapa: el while no tiene salida. Se resolverá con la condición de fin de juego (Día 21) Errores frecuentes del Tema 2

12. 📋 Matriz de trazabilidad

Contenido original Archivo de origen Concepto desarrollado Ejercicio original Reto adicional Proyecto relacionado
Objetivos y los 7 pasos 146 Sección 0 — — Sección 6
setup, bgcolor, title, cuerpo con tuplas 147 Tema 1 Tres segmentos alineados Retos 1–4 del Tema 1 Secciones 6, 7 y 8
tracer, update, sleep, animación 148 Tema 2 Experimento con update Retos 1–4 del Tema 2 Secciones 6, 7 y 8
Segmentos que siguen a la cabeza, range con paso 148 Tema 3 Algoritmo de movimiento Retos 1–4 del Tema 3 Secciones 6 y 7
Clase Snake, constantes 149 Tema 4 Refactorizar a snake.py Retos 1–4 del Tema 4 Sección 8
Control con flechas, no devolverse 150 Tema 5 Métodos up, down, left, right Depuración del giro rápido Secciones 6 y 8
Programar no es memorizar 151 Sección 0 — — Sección 10
(No existe en el curso original) — — — Tren de la Ruta Escolar Sección 7
(No existe en el curso original) — — — Duelo de Serpientes Sección 8

13. 📦 Evidencias de aprendizaje del Día 20

  • Juego de la serpiente (pasos 1 a 3) funcionando, con snake.py y main.py.
  • Dibujo en papel cuadriculado del algoritmo del movimiento durante 4 vueltas con un giro.
  • Explicación escrita del error del giro rápido y la corrección propuesta.
  • Proyecto extra (Tren de la Ruta Escolar) o integrador (Duelo de Serpientes).
  • Cuaderno de errores: pantalla negra por tracer(0) sin update(), range con palabras clave, IndexError por self.head antes de crear la serpiente, heading sin paréntesis y segmentos apilados.