Глава 7 · Глубокое погружение в Turtle

Мини-проект — часы без времени

Узнаваемый циферблат — просто геометрия: деления через равные углы, числа, две стрелки на фиксированных направлениях.

Что мы построим

«Часы без времени» — статичный циферблат аналоговых часов. Модуль datetime нам пока не нужен — стрелки встанут на фиксированный угол, просто чтобы показать, как из геометрии собирается узнаваемый объект.

chasy_polnye.py
import turtle

screen = turtle.Screen()
screen.setup(width=420, height=420)
artist = turtle.Turtle()
artist.speed(0)
artist.pencolor("#0D0230")
artist.pensize(3)

# circle(150) центрирует круг в 150 px СЛЕВА от текущего курса —
# поэтому стартуем на 150 ниже (0, -150), чтобы центр циферблата попал в (0, 0)
artist.penup()
artist.goto(0, -150)
artist.pendown()
artist.circle(150)

for hour in range(12):
    artist.penup()
    artist.goto(0, 0)
    artist.setheading(90 - hour * 30)
    artist.forward(135)
    artist.pendown()
    artist.forward(15)
    artist.penup()

for hour, label in [(0, "12"), (3, "3"), (6, "6"), (9, "9")]:
    artist.goto(0, 0)
    artist.setheading(90 - hour * 30)
    artist.forward(110)
    artist.write(label, align="center", font=("Arial", 16, "bold"))

artist.pensize(5)
artist.pencolor("#5B24F9")
artist.goto(0, 0)
artist.setheading(90 - 12 * 30)
artist.pendown()
artist.forward(80)
artist.penup()

artist.pensize(3)
artist.pencolor("#DB2777")
artist.goto(0, 0)
artist.setheading(90 - 2 * 30)
artist.pendown()
artist.forward(120)

screen.exitonclick()
Результат выполнения
Циферблат аналоговых часов с делениями на 12 часов, числами 12, 3, 6, 9 и двумя стрелками, показывающими фиксированное время
Готовый результат: циферблат с делениями, числами 12/3/6/9 и двумя стрелками

Геометрический план

12 делений циферблата расположены по кругу через равные промежутки — знакомая формула 360 / 12 = 30 градусов между соседними часами. Но в отличие от обычного многоугольника, здесь удобнее задавать угол каждого деления АБСОЛЮТНО, через setheading(), а не накапливать поворотами:

ugol_deleniya.py
# час 0 (12 часов) — направление вверх, 90°
# час 3            — направление вправо, 0°
# час 6            — направление вниз, -90°
# час 9            — направление влево, 180°
# в общем виде: ugol = 90 - hour * 30

Шаг 1: окружность и деления

chasy_delenia.py
import turtle

screen = turtle.Screen()
screen.setup(width=420, height=420)
artist = turtle.Turtle()
artist.speed(0)
artist.pencolor("#0D0230")
artist.pensize(3)

# circle(150) центрирует круг в 150 px СЛЕВА от текущего курса —
# поэтому стартуем на 150 ниже (0, -150), чтобы центр циферблата попал в (0, 0)
artist.penup()
artist.goto(0, -150)
artist.pendown()
artist.circle(150)

for hour in range(12):
    artist.penup()
    artist.goto(0, 0)
    artist.setheading(90 - hour * 30)
    artist.forward(135)
    artist.pendown()
    artist.forward(15)
    artist.penup()

screen.exitonclick()
Результат выполнения
Круглый циферблат с двенадцатью короткими штрихами-делениями по кругу, без цифр и стрелок
Шаг 1 — окружность и 12 делений, без чисел и стрелок
chasy_delenia_kod.py
artist.circle(150)

for hour in range(12):
    artist.penup()
    artist.goto(0, 0)
    artist.setheading(90 - hour * 30)
    artist.forward(135)
    artist.pendown()
    artist.forward(15)
    artist.penup()
Почему goto(0, 0) перед каждым делением
Каждое деление начинается заново от центра — иначе черепашка рисовала бы деления одно за другим по кругу, а не как независимые лучи от центра. penup()/pendown() вокруг каждого шага гарантирует, что линии между делениями не будет.

Шаг 2: числа и стрелки

chasy_chisla_strelki_kod.py
for hour, label in [(0, "12"), (3, "3"), (6, "6"), (9, "9")]:
    artist.goto(0, 0)
    artist.setheading(90 - hour * 30)
    artist.forward(110)
    artist.write(label, align="center", font=("Arial", 16, "bold"))

# часовая стрелка — короче, толще, фиксирована на 12
artist.pensize(5)
artist.pencolor("#5B24F9")
artist.goto(0, 0)
artist.setheading(90 - 12 * 30)
artist.pendown()
artist.forward(80)
artist.penup()

# минутная стрелка — длиннее, тоньше, фиксирована на 2
artist.pensize(3)
artist.pencolor("#DB2777")
artist.goto(0, 0)
artist.setheading(90 - 2 * 30)
artist.pendown()
artist.forward(120)

Готовый результат

chasy_polnye.py
import turtle

screen = turtle.Screen()
screen.setup(width=420, height=420)
artist = turtle.Turtle()
artist.speed(0)
artist.pencolor("#0D0230")
artist.pensize(3)

# circle(150) центрирует круг в 150 px СЛЕВА от текущего курса —
# поэтому стартуем на 150 ниже (0, -150), чтобы центр циферблата попал в (0, 0)
artist.penup()
artist.goto(0, -150)
artist.pendown()
artist.circle(150)

for hour in range(12):
    artist.penup()
    artist.goto(0, 0)
    artist.setheading(90 - hour * 30)
    artist.forward(135)
    artist.pendown()
    artist.forward(15)
    artist.penup()

for hour, label in [(0, "12"), (3, "3"), (6, "6"), (9, "9")]:
    artist.goto(0, 0)
    artist.setheading(90 - hour * 30)
    artist.forward(110)
    artist.write(label, align="center", font=("Arial", 16, "bold"))

artist.pensize(5)
artist.pencolor("#5B24F9")
artist.goto(0, 0)
artist.setheading(90 - 12 * 30)
artist.pendown()
artist.forward(80)
artist.penup()

artist.pensize(3)
artist.pencolor("#DB2777")
artist.goto(0, 0)
artist.setheading(90 - 2 * 30)
artist.pendown()
artist.forward(120)

screen.exitonclick()
Результат выполнения
Циферблат аналоговых часов с делениями на 12 часов, числами 12, 3, 6, 9 и двумя стрелками, показывающими фиксированное время
Готовый результат: циферблат с делениями, числами 12/3/6/9 и двумя стрелками
★ Базовая практика
Все 12 чисел

Добавьте оставшиеся 8 чисел (1, 2, 4, 5, 7, 8, 10, 11) по тому же принципу.

★★ Самостоятельная задача
Секундная стрелка

Добавьте третью, самую тонкую стрелку — секундную — на любой фиксированный угол.

★★★ Задача повышенной сложности
Другое время

Измените углы часовой и минутной стрелки, чтобы часы показывали другое (тоже фиксированное) время.

Практика: часы без времени
Модуль turtle открывает нативное окно Python — выполните локально в VS Code, PyCharm или Jupyter
Практика выполняется локально
Открыть практику →