Найти в Дзене

Пишем змейку на Python и Turtle: Как я научил рептилию кусать собственный хвост (и не умер от смеха)

Привет, мой юный падаван (или умудренный опытом ниндзя, которому просто скучно на удаленке)!
Помните те времена, когда змейка в телефоне была единственной вещью, которая могла отвлечь вас от скучной лекции в универе? Мы водили черную полоску из пикселей за зелеными квадратиками, думая: «Эх, вот бы сейчас свою игру написать». Время пришло! Только хватит страдать с суровым PyGame. У нас есть Python и черепашка Turtle. Да-да, та самая черепашка, которую в школе заставляли рисовать квадратики. Сейчас она будет ползать по экрану, изображая наше змеиное тельце. Мы с вами начинали делать что-то подобное, я публиковал видео, сейчас сделаем до конца. Погнали! Всего лишь: Кода будет много, но не пугайтесь. Мы разберем его по косточкам (или по пикселям?). Первым делом мы должны сказать Python, что нам понадобятся модули. Turtle встроен в стандартную библиотеку, а random и `time» нам тоже пригодятся. import turtle
import time
import random Если вы сейчас запустите код и у вас не вылетела ошибк
Оглавление

Привет, мой юный падаван (или умудренный опытом ниндзя, которому просто скучно на удаленке)!
Помните те времена, когда змейка в телефоне была единственной вещью, которая могла отвлечь вас от скучной лекции в универе? Мы водили черную полоску из пикселей за зелеными квадратиками, думая: «Эх, вот бы сейчас свою игру написать».

Время пришло! Только хватит страдать с суровым PyGame. У нас есть Python и черепашка Turtle.

Да-да, та самая черепашка, которую в школе заставляли рисовать квадратики. Сейчас она будет ползать по экрану, изображая наше змеиное тельце. Мы с вами начинали делать что-то подобное, я публиковал видео, сейчас сделаем до конца. Погнали!

А что нам надо?

Всего лишь:

  1. Компьютер (да, без него никак, простите).
  2. Установленный Python (если не установлен — гугли, солдат, ребенка не игра).
  3. Чувство юмора и немного наглости.

Кода будет много, но не пугайтесь. Мы разберем его по косточкам (или по пикселям?).

Шаг 1. Импортируем тяжелую артиллерию

Первым делом мы должны сказать Python, что нам понадобятся модули. Turtle встроен в стандартную библиотеку, а random и `time» нам тоже пригодятся.

import turtle
import time
import random

Если вы сейчас запустите код и у вас не вылетела ошибка — вы великолепны! Можете налить себе чаю.

Шаг 2. Создаем сцену (или «Поле боя»)

Наша змея не должна жить в пустоте. Ей нужен загон. Для чистоты эксперимента, пусть это будет черный прямоугольник. (Классика! Все лучшее в этой жизни — черное).

# Настройки окна
win = turtle.Screen()
win.title("Змейка на минималках, но с душой")
win.bgcolor("black")
win.setup(width=600, height=600)
win.tracer(0) # Отключаем анимацию обновления экрана вручную, чтобы змея не дергалась как ужаленная

win.tracer(0) — это наш способ сказать черепашке: «Цыц! Не обновляй экран сама, я сам знаю, когда надо». Иначе будет лагать.

Шаг 3. Рисуем Еду (или «Квадратный счастье»)

Наша змея — хищник. Она охотится на красные квадратики. Создадим для нее добычу.

# Еда
food = turtle.Turtle()
food.speed(0)
food.shape("square")
food.color("red")
food.penup() # Чтобы не рисовала линию за собой, когда ползет
food.goto(0, 100) # Пусть пока повисит где-то сверху

Почему penup()? Потому что если мы этого не сделаем, еда, перемещаясь, будет оставлять за собой кровавый след. А нам лишнее расчленение на экране ни к чему.

Шаг 4. Создаем Тело Змея (или «Коллективную ответственность»)

Самое сложное — это змея. Она будет состоять из сегментов. Голова — отдельная черепаха, а хвост — это список черепах.

# Голова
head = turtle.Turtle()
head.speed(0)
head.shape("square")
head.color("green")
head.penup()
head.goto(0, 0)
head.direction = "stop" # Стоит на месте, типа думает, жить ей или уже ползти

# Список для хвоста
segments = []

Шаг 5. Анатомия движения (или «Как заставить рептилию слушаться»)

Нужно научить змею реагировать на стрелки. Для этого создадим функции, которые будут менять направление головы. Но с условием: нельзя разворачиваться на 180 градусов, иначе змея сломает себе шею (и игру).

# Функции управления
def go_up():
if head.direction != "down": # Нельзя ехать вниз, если едешь вверх
head.direction = "up"

def go_down():
if head.direction != "up":
head.direction = "down"

def go_left():
if head.direction != "right":
head.direction = "left"

def go_right():
if head.direction != "left":
head.direction = "right"

# Слушаем кнопки
win.listen()
win.onkeypress(go_up, "Up")
win.onkeypress(go_down, "Down")
win.onkeypress(go_left, "Left")
win.onkeypress(go_right, "Right")

Теперь если нажать на стрелку, змея изменит курс. Прямо как на переговорах, меняем решение в последний момент.

Шаг 6. Двигаем тело (или «Логика для программистов с Артрозом»)

Здесь магия. Чтобы хвост полз за головой, мы будем двигать сегменты хвоста на место предыдущего. Проще говоря: берем последний вагон и тащим его туда, где был предыдущий.

Создадим функцию move().

python

def move():
# Двигаем хвост с конца
for index in range(len(segments) - 1, 0, -1):
x = segments[index - 1].xcor()
y = segments[index - 1].ycor()
segments[index].goto(x, y)

# Если есть хвост, двигаем его первый элемент на место головы
if len(segments) > 0:
x = head.xcor()
y = head.ycor()
segments[0].goto(x, y)

# Двигаем голову
if head.direction == "up":
head.sety(head.ycor() + 20)
if head.direction == "down":
head.sety(head.ycor() - 20)
if head.direction == "left":
head.setx(head.xcor() - 20)
if head.direction == "right":
head.setx(head.xcor() + 20)

Почему 20? Потому что наш квадратик (shape «square») по умолчанию 20х20 пикселей. Мы ползем четко по сетке.

Шаг 7. Игровой цикл (или «А будет ли это работать вечно?»)

Теперь самое мясо. Это бесконечный цикл, где живет наша игра.

Пока всё, что мы написали — это сценарий. Цикл — это режиссер, который кричит «Мотор!».

# Основной игровой цикл
while True:
win.update() # Обновляем экран (наш ручной режим)

# Проверка на столкновение с едой
if head.distance(food) < 20:
# Перемещаем еду в случайное место
x = random.randint(-280, 280)
y = random.randint(-280, 280)
food.goto(x, y)

# Добавляем новый сегмент хвоста
new_segment = turtle.Turtle()
new_segment.speed(0)
new_segment.shape("square")
new_segment.color("grey") # Пусть хвост будет серым, чтоб голову выделить
new_segment.penup()
segments.append(new_segment)

# Двигаем всю конструкцию
move()

# Проверка на столкновение со стенами (Game Over)
if head.xcor() > 290 or head.xcor() < -290 or head.ycor() > 290 or head.ycor() < -290:
time.sleep(1)
head.goto(0, 0)
head.direction = "stop"

# Прячем старый хвост
for seg in segments:
seg.goto(1000, 1000)
# Отправляем в ссылку на Урал
segments.clear()
# Очищаем список

# Проверка на столкновение с собственным хвостом
for seg in segments:
if seg.distance(head) < 20:
time.sleep(1)
head.goto(0, 0)
head.direction = "stop"
for seg in segments:
seg.goto(1000, 1000)
segments.clear()

time.sleep(0.1)
# Задержка, чтобы змея не летела как ракета

Разберем страшные моменты:

  1. Еда: Если голова коснулась еды (расстояние < 20), еда прыгает в новое место. А мы добавляем ей серый сегмент в зад... в смысле, в хвост.
  2. Стены: Если голова улетела за 290 (окно 600, минус пол-головы), то игра останавливается, мы убираем хвост в небытие (координаты 1000, 1000 — типа ссылка в Сибирь), а голову ставим в центр.
  3. Самопоедание: Тут всё жестко. Если любой сегмент хвоста коснулся головы — всё сначала.

Финальный аккорд

Чтобы окно не закрылось само, добавим в самый конец:

win.mainloop()
-2

Вот и всё! Теперь у вас есть своя змейка.


Возможные баги и их философское осмысление:

  1. Змея движется рывками: Вы забыли win.update() или убрали tracer(0). Черепаха просто не успевает за вашими амбициями.
  2. Хвост не растет: Вы положили еду, а сегмент не добавили? Или забыли .append(new_segment)? Хвост — это серьезно, без него змея — просто червяк.
  3. Змея проходит сквозь стены: Ну, если вы убрали проверку на стену, то у вас не змейка, а призрак. Тоже вариант, но мы же пишем хардкорный симулятор рептилии.

Запускайте код и наслаждайтесь!

Почувствуйте себя программистом из 90-х, только с более мощным компьютером и возможностью выложить это в Дзен.

Пишите в комментариях, сколько у вас получилось съесть еды до первого самосожжения (самоукушения). И не забывайте: идеальных программ не бывает, бывают те, которые допилили до конца!

P.S. Если змейка начала странно ругаться матом на английском — проверьте, не нажали ли вы CapsLock. В коде это не страшно, но черепахи обидчивые.