Форум программистов, компьютерный форум, киберфорум
EggHead
Войти
Регистрация
Восстановить пароль

Исполнитель Чертежник в КуМир: Решение задач

Запись от EggHead размещена 16.03.2025 в 13:22
Показов 2206 Комментарии 0

Нажмите на изображение для увеличения
Название: 80b61fb0-fa43-45c5-8733-c4d81cdaa3a5.jpg
Просмотров: 45
Размер:	219.2 Кб
ID:	10422
Представьте, что вы можете рисовать на бесконечной координатной плоскости, перемещая точку, которая оставляет след. По вашей команде она может поднять перо и двигаться, не оставляя следа, или опустить его и вычерчивать линии. Именно так работает исполнитель Чертёжник в системе КуМир — учебной среде программирования, разработанной для обучения школьников основам алгоритмизации.

Чертёжник — один из самых наглядных и интуитивно понятных исполнителей в КуМире. Его главное предназначение — помочь новичкам освоить фундаментальные концепции программирования через визуальные результаты своих алгоритмов. Когда код превращается в геометрические фигуры на экране, абстрактные понятия становятся осязаемыми и понятными даже для тех, кто только начинает свой путь в мире программирования. Работа с Чертёжником напоминает управление настоящей черепахой из языка Logo, только в более строгой математической среде. Вместо относительных поворотов и перемещений, здесь мы оперируем конкретными координатами на плоскости. Это делает Чертёжника отличным инструментом не только для изучения алгоритмов, но и для лучшего понимания координатной геометрии.

Сама суть Чертёжника заключается в его простоте. У него есть всего несколько базовых команд:
  • сместиться в точку x, y — переместить перо в указанную точку.
  • опустить перо — начать рисовать при перемещении.
  • поднять перо — прекратить рисование при перемещении.

Помимо этого, существуют и полезные производные команды, например сместиться на вектор (a, b), позволяющая указать относительное смещение от текущей позиции. Несмотря на ограниченный набор команд, с их помощью можно создавать удивительно сложные и красивые рисунки. От простых геометрических фигур до комплексных орнаментов и даже фракталов — всё зависит только от вашей фантазии и умения составлять алгоритмы.

Система координат в Чертёжнике стандартная декартова: начало координат находится в левом нижнем углу, ось X направлена вправо, ось Y — вверх. Каждая точка на плоскости однозначно определяется парой чисел (x, y). При запуске система автоматически устанавливает перо в точку (0, 0) с поднятым пером. Чтобы нарисовать даже простейший отрезок, нам нужно:
1. Переместиться в начальную точку отрезка.
2. Опустить перо.
3. Переместиться в конечную точку.
4. Поднять перо (если дальше нужно перемещаться без рисования).

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

Когда я впервые столкнулся с Чертёжником, меня поразило, насколько быстро можно получить видимый результат своей работы. Даже простой код из 5-7 строк уже создает что-то осмысленное на экране. А когда доходишь до использования циклов и вспомогательных алгоритмов, возможности расширяются в геометрической прогрессии.

Важная особенность работы с Чертёжником — необходимость мыслить алгоритмически. Нужно разбивать сложный рисунок на простые элементы, выявлять повторяющиеся части и оптимизировать траекторию движения. Эти навыки оказываются полезными не только в программировании, но и в решении многих жизненных задач.

В следующих разделах мы детально рассмотрим команды Чертёжника, разберем систему координат, а затем перейдем к решению конкретных практических задач — от простейших до весьма нетривиальных.

Базовые команды и система координат



Чтобы эффективно управлять Чертёжником, необходимо детально разобраться в его командной системе и особенностях работы в координатном пространстве. Эти знания станут фундаментом для решения всех последующих задач. Система координат в Чертёжнике представляет собой классическую декартову плоскость, где каждая точка определяется парой чисел (x, y). Ось X направлена горизонтально слева направо, а ось Y — вертикально снизу вверх. При запуске программы перо автоматически устанавливается в начало координат — точку (0, 0). Весь функционал Чертёжника строится вокруг нескольких базовых команд, которые в совокупности позволяют создать любой рисунок. Разберём их подробно.
  • опустить перо — после выполнения этой команды Чертёжник начинает оставлять след при перемещении. Все последующие передвижения будут сопровождаться прорисовкой линий.
  • поднять перо — противоположная предыдущей команда. После её выполнения Чертёжник перестаёт оставлять след при перемещении, что позволяет перейти к новой точке без рисования соединительной линии.
  • сместиться в точку x, y — ключевая команда для перемещения. Она перемещает перо Чертёжника в точку с абсолютными координатами (x, y). Например, команда сместиться в точку 5, 8 передвинет перо в точку с координатами x=5, y=8.
  • сместиться на вектор (a, b) — эта команда выполняет относительное перемещение. Перо сдвигается на a единиц по оси X и b единиц по оси Y от текущего положения. Например, если перо находится в точке (3, 4), то команда сместиться на вектор (2, -1) переместит его в точку (5, 3).

Важно понимать разницу между абсолютным и относительным перемещением. В первом случае мы указываем конкретные координаты точки назначения, а во втором — насколько нужно сдвинуться относительно текущего положения. Выбор типа перемещения зависит от конкретной задачи и может существенно влиять на сложность кода. Рассмотрим простой пример. Допустим, нам нужно нарисовать квадрат со стороной 5 единиц, начиная из точки (2, 3):

Code
1
2
3
4
5
6
7
8
9
10
алг квадрат
нач
  сместиться в точку 2, 3
  опустить перо
  сместиться в точку 7, 3
  сместиться в точку 7, 8
  сместиться в точку 2, 8
  сместиться в точку 2, 3
  поднять перо
кон
Тот же самый квадрат можно нарисовать, используя относительные перемещения:

Code
1
2
3
4
5
6
7
8
9
10
алг квадрат_через_вектор
нач
  сместиться в точку 2, 3
  опустить перо
  сместиться на вектор (5, 0)
  сместиться на вектор (0, 5)
  сместиться на вектор (-5, 0)
  сместиться на вектор (0, -5)
  поднять перо
кон
Оба варианта дают один и тот же результат, но в разных ситуациях один может быть удобнее другого. Например, при рисовании симметричных фигур часто проще использовать относительные перемещения, а при работе с фиксированными точками — абсолютные координаты.

В Чертёжнике также можно использовать составные команды, объединяющие несколько базовых. Например, частая операция — переместиться в новую точку с опущенным пером (т.е. нарисовать линию из текущей позиции). Это можно записать более компактно:

Code
1
2
3
4
5
алг линия(x, y)
нач
  опустить перо
  сместиться в точку x, y
кон
При работе с Чертёжником я часто замечал одну особенность: новички стремятся использовать только абсолютные координаты, что приводит к громоздким и трудно модифицируемым программам. Между тем, комбинирование абсолютных и относительных перемещений обычно дает более элегантное решение.

Еще один важный аспект — понимание масштаба. В КуМире координаты могут быть как целыми, так и дробными числами. Это позволяет регулировать детализацию рисунка. При этом видимая область координатной плоскости зависит от настроек среды и может быть изменена.

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

Задача Гиа: какая фигура появится на экране при выполнении Исполнителем Черепашка данного алгоритма?
Исполнитель Черепашка перемещается на экране компьютера, оставляя след в виде линии. В каждый конкретный момент известно положение исполнителя и...

[КуМир] Нарисовать график функции y = tg(x+1)^2, исполнитель Рисователь
Ребят, простите дурака, но я не знаю где найти нужный форум по КУМИРУ, но так как он мне безумно напоминает Паскаь, пишу суда. Нужно...

Исполнитель Робот
дали вот несколько задач (попросили решить, будучи студентом уже не ничего помню из курса информатики), можете проверить 1-3 и объяснить как делать...

Исполнитель КУЗНЕЧИК живёт на числовой оси
Исполнитель КУЗНЕЧИК живёт на числовой оси. Начальное положение КУЗНЕЧИКА – точка 0. Система команд Кузнечика: Вперед 5 – Кузнечик прыгает вперёд...


Алгоритмические основы работы с Чертежником



Работа с Чертежником в системе КуМир не ограничивается только простыми линейными последовательностями команд. Настоящая мощь этого исполнителя раскрывается, когда мы начинаем использовать алгоритмические конструкции — циклы и условия. Циклические конструкции — это настоящее спасение при рисовании регулярных структур. Представьте, что вам нужно нарисовать многоугольник с 20 сторонами. Писать 20 различных команд перемещения было бы утомительно и неэффективно. Циклы позволяют решить эту проблему элегантно.

В КуМире для организации циклов можно использовать конструкцию нц ... кц (начало цикла — конец цикла). Рассмотрим несколько вариантов цикла:

1. Цикл с заданным числом повторений:

Code
1
2
3
нц для i от 1 до n
   | команды, которые нужно повторить n раз
кц
2. Цикл с условием:

Code
1
2
3
нц пока <условие>
   | команды, выполняемые пока условие истинно
кц
3. Цикл с постусловием:

Code
1
2
3
4
нц
   | команды, которые выполняются хотя бы один раз
до <условие>
кц
Давайте применим циклы на практике. Например, нарисуем правильный шестиугольник:

Code
1
2
3
4
5
6
7
8
9
10
алг шестиугольник(сторона)
нач
  | предполагаем, что находимся в центре шестиугольника
  сместиться на вектор (0, сторона)  | перемещаемся в верхнюю вершину
  опустить перо
  нц для i от 1 до 6
    сместиться на вектор (сторона*cos(pi/3*(i-1)+pi/6), сторона*sin(pi/3*(i-1)+pi/6))
  кц
  поднять перо
кон
Этот код использует параметрический способ задания координат вершин правильного многоугольника. Для шестиугольника угол между соседними вершинами составляет 60 градусов (π/3 радиан).
Другая фундаментальная конструкция — условный оператор. В КуМире он представлен в виде:

Code
1
2
3
4
5
если <условие> то
   | команды, выполняемые при истинности условия
иначе
   | команды, выполняемые при ложности условия
все
Условия особенно полезны при создании сложных рисунков, где траектория движения Чертежника зависит от определенных параметров. Например, можно создать алгоритм, который рисует разные фигуры в зависимости от входного параметра:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
алг выбор_фигуры(тип, размер)
нач
  если тип = 1 то
    | рисуем квадрат
    сместиться в точку 0, 0
    опустить перо
    нц для i от 1 до 4
      сместиться на вектор (размер, 0)
      сместиться на вектор (0, размер)
      сместиться на вектор (-размер, 0)
      сместиться на вектор (0, -размер)
    кц
    поднять перо
  иначе
    если тип = 2 то
      | рисуем круг (аппроксимация многоугольником)
      сместиться в точку размер, 0
      опустить перо
      нц для i от 1 до 36
        сместиться на вектор (размер*cos(i*10*pi/180) - размер*cos((i-1)*10*pi/180), 
                              размер*sin(i*10*pi/180) - размер*sin((i-1)*10*pi/180))
      кц
      поднять перо
    иначе
      | рисуем треугольник
      сместиться в точку 0, 0
      опустить перо
      сместиться на вектор (размер, 0)
      сместиться на вектор (-размер/2, размер*sqrt(3)/2)
      сместиться на вектор (-размер/2, -размер*sqrt(3)/2)
      поднять перо
    все
  все
кон
Этот алгоритм демонстрирует гибкость, которую дают условные операторы. Он может рисовать квадрат, аппроксимацию круга или равносторонний треугольник в зависимости от значения параметра "тип".

Отладка кода — ещё одна важная тема при работе с Чертежником. КуМир предоставляет несколько инструментов для отладки:
1. Пошаговое выполнение — позволяет наблюдать, как Чертежник выполняет каждую команду.
2. Точки останова — можно установить в местах, где предположительно возникают ошибки.
3. Наблюдение за значениями переменных — помогает отследить изменения параметров в процессе выполнения.

При отладке программ для Чертежника уделяйте особое внимание координатам. Часто ошибки возникают из-за неправильного расчета положения или неучтённой особенности системы координат. Визуальная природа Чертежника может как помочь в выявлении ошибок (наглядно видны неправильные линии), так и затруднить диагностику (непонятно, почему линия пошла не туда).

Начинающие программисты часто совершают несколько типичных ошибок при работе с Чертежником:
1. Забывают опускать или поднимать перо в нужных местах.
2. Путают абсолютные и относительные координаты.
3. Не учитывают, что после выполнения цикла Чертежник оказывается в определённой позиции.
4. Неправильно расчитывают координаты при създании сложных фигур.

Чтобы избежать этих ошибок, полезно заранее продумать траекторию движения Чертежника, возможно, даже нарисовать её на бумаге с указанием всех ключевых точек. Также стоит комментировать код, объясняя, какую часть рисунка вычерчивает тот или иной блок программы. Еще один типичный сценарий работы с Чертежником — создание повторяющихся элементов с небольшими вариациями. Здесь на помощь приходит комбинация циклов и переменных. Например, чтобы нарисовать группу концентрических окружностей с увеличивающимся радиусом:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
алг концентрические_окружности(количество, шаг)
нач
нц для i от 1 до количество
  | рисуем окружность через параметрические уравнения
  сместиться в точку i*шаг, 0
  опустить перо
  нц для угол от 0 до 359 шаг 10
    | переходим к следующей точке окружности
    сместиться в точку i*шаг*cos(угол*pi/180), i*шаг*sin(угол*pi/180)
  кц
  поднять перо
кц
кон
Иногда при работе с Чертежником возникает необходимость вычислить положение точки относительно уже нарисованных элементов. В таких случаях критически важно грамотно использовать переменные для хранения промежуточных координат:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
алг ромб_с_диагоналями(сторона)
нач
цел x1, y1, x2, y2, x3, y3, x4, y4
| вычисляем координаты вершин ромба
x1 := 0
y1 := 0
x2 := сторона
y2 := сторона
x3 := 2*сторона
y3 := 0
x4 := сторона
y4 := -сторона
 
| рисуем контур ромба
сместиться в точку x1, y1
опустить перо
сместиться в точку x2, y2
сместиться в точку x3, y3
сместиться в точку x4, y4
сместиться в точку x1, y1
поднять перо
 
| рисуем диагонали
сместиться в точку x1, y1
опустить перо
сместиться в точку x3, y3
поднять перо
сместиться в точку x2, y2
опустить перо
сместиться в точку x4, y4
поднять перо
кон
Одна из самых неприятных ошибок при работе с Чертёжником — выход за пределы видимой области. Если ваша фигура неожиданно исчезла из поля зрения, проверьте, не содержит ли ваш алгоритм слишком больших значений координат или накапливающихся погрешностей при вычислениях. Я однажды потратил почти час на поиск ошибки в алгоритме рисования снежинки Коха, пока не понял, что проблема заключалась в незаметном накоплении погрешности при вычислении координат. Каждая итерация вносила маленькую ошибку, которая в итоге привела к заметному искажению рисунка. Решилось это округлением значений:

Code
1
2
x := round(x*100)/100
y := round(y*100)/100
Умение эффективно отлаживать код — одно из ключевых умений при работе с Чертёжником. Вот несколько полезных приёмов:
1. Рисуйте координатные оси или сетку в начале программы — это поможет вам визуально ориентироваться в пространстве.
2. Добавляйте вспомогательные точки, которые помогут понять, где именно находится Чертёжник в ключевые моменты выполнения алгоритма.
3. Используйте разные цвета для разных частей рисунка (если среда это поддерживает).

Когда алгоритм становится сложным, полезно введение пошаговой отладки с контрольными точками. Например, при рисовании домика можно сначала убедиться, что правильно нарисован фундамент, затем стены, крыша и т.д. На каждом этапе проверяйте, соответствует ли текущий результат вашим ожиданиям.

Довольно часто в задачах требуется создать нечто более сложное, чем просто набор линий. В таких случаях удобно комбинировать базовые алгоритмические конструкции. Вот пример рисования шахматной доски, где используются вложенные циклы:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
алг шахматная_доска(размер_клетки, количество_клеток)
нач
нц для i от 0 до количество_клеток-1
  нц для j от 0 до количество_клеток-1
    | Заливаем клетку, если сумма индексов четная
    если (i + j) mod 2 = 0 то
      | рисуем закрашенную клетку
      сместиться в точку i*размер_клетки, j*размер_клетки
      опустить перо
      нц для k от 0 до размер_клетки шаг 1
        сместиться в точку i*размер_клетки + k, j*размер_клетки
        сместиться в точку i*размер_клетки + k, j*размер_клетки + размер_клетки
      кц
      поднять перо
    все
  кц
кц
кон
Приведенный алгоритм рисует шахматную доску, заполняя клетки горизонтальными линиями. Обратите внимание на вложенность циклов: внешние циклы перебирают клетки, а внутренний цикл заполняет каждую клетку линиями.

Освоение работы с циклами и условиями в Чертёжнике закладывает необходимый фундамент для решения более сложных задач. Именно эти алгоритмические конструкции позволяют от простых линий перейти к созданию геометрических фигур, узоров и даже художественных эффектов.

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

Вспомогательные алгоритмы для оптимизации кода



Работа над сложными графическими задачами в Чертёжнике часто приводит к объемным и запутанным программам. К счастью, система КуМир поддерживает создание вспомогательных алгоритмов, которые позволяют структурировать код, избежать повторений и сделать программу более понятной. Вспомогательный алгоритм в КуМире — это фактически подпрограмма, которую можно вызывать из основного алгоритма. Он может принимать параметры и выполнять определённую последовательность действий. Рассмотрим простой пример:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
алг линия(х1, у1, х2, у2)
| Рисует линию между двумя точками
нач
сместиться в точку х1, у1
опустить перо
сместиться в точку х2, у2
поднять перо
кон
 
алг квадрат(х, у, сторона)
| Рисует квадрат с левым нижним углом в точке (х,у)
нач
линия(х, у, х+сторона, у)
линия(х+сторона, у, х+сторона, у+сторона)
линия(х+сторона, у+сторона, х, у+сторона)
линия(х, у+сторона, х, у)
кон
 
алг основной
нач
квадрат(0, 0, 10)
квадрат(20, 20, 5)
кон
В этом примере мы создали два вспомогательных алгоритма: линия и квадрат. Алгоритм квадрат использует линия для рисования сторон, а основной алгоритм вызывает квадрат дважды с разными параметрами. Такая структура делает код более читаемым и упрощает его поддержку.

Одно из главных преимуществ вспомогательных алгоритмов — возможность создания библиотеки стандартных графических примитивов. Однажды написав алгоритмы для часто используемых фигур (круг, прямоугольник, многоугольник), вы сможете многократно применять их в различных проектах. Вот пример более развитой библиотеки геометрических фигур:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
алг прямоугольник(х, у, ширина, высота)
нач
линия(х, у, х+ширина, у)
линия(х+ширина, у, х+ширина, у+высота)
линия(х+ширина, у+высота, х, у+высота)
линия(х, у+высота, х, у)
кон
 
алг окружность(x_центра, y_центра, радиус)
нач
сместиться в точку x_центра+радиус, y_центра
опустить перо
нц для угол от 0 до 359
  сместиться в точку x_центра+радиус*cos(угол*pi/180), y_центра+радиус*sin(угол*pi/180)
кц
поднять перо
кон
 
алг треугольник(x1, y1, x2, y2, x3, y3)
нач
линия(x1, y1, x2, y2)
линия(x2, y2, x3, y3)
линия(x3, y3, x1, y1)
кон
 
алг многоугольник(x_центра, y_центра, радиус, количество_сторон)
нач
вещ угол_шаг
угол_шаг := 2*pi/количество_сторон
сместиться в точку x_центра+радиус, y_центра
опустить перо
нц для i от 1 до количество_сторон
  сместиться в точку x_центра+радиус*cos(i*угол_шаг), y_центра+радиус*sin(i*угол_шаг)
кц
поднять перо
кон

Вспомогательные алгоритмы для оптимизации кода



Имея в своём арсенале набор готовых графических примитивов, мы можем приступить к созданию более сложных изображений. Ключевой подход к эффективному программированию Чертёжника — композиция. Это когда мы создаём сложные рисунки путём комбинирования простых элементов. Давайте разработаем алгоритм для рисования домика. Мы можем представить его как комбинацию прямоугольника (стены) и треугольника (крыша):

Code
1
2
3
4
5
алг дом(х, у, ширина, высота)
нач
  прямоугольник(х, у, ширина, высота)
  треугольник(х, у+высота, х+ширина/2, у+высота+ширина/2, х+ширина, у+высота)
кон
Создав такой алгоритм, мы можем рисовать домики разного размера в разных частях координатной плоскости. Теперь добавим окна и дверь:

Code
1
2
3
4
5
6
7
8
9
10
11
алг дом_с_деталями(х, у, ширина, высота)
нач
  дом(х, у, ширина, высота)
  
  | Дверь (20% ширины, 40% высоты дома)
  прямоугольник(х+ширина*0.4, у, ширина*0.2, высота*0.4)
  
  | Окна (по 15% ширины и высоты дома)
  прямоугольник(х+ширина*0.2, у+высота*0.6, ширина*0.15, высота*0.15)
  прямоугольник(х+ширина*0.65, у+высота*0.6, ширина*0.15, высота*0.15)
кон
Параметризация вспомогательных алгоритмов — ещё один мощный приём оптимизации. Добавляя параметры, мы делаем алгоритмы более гибкими и универсальными. Например, можно создать алгоритм для рисования звезды с произвольным числом лучей:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
алг звезда(х_центра, у_центра, внешний_радиус, внутренний_радиус, количество_лучей)
нач
  вещ угловой_шаг, угол
  угловой_шаг := pi/количество_лучей
  
  сместиться в точку х_центра+внешний_радиус, у_центра
  опустить перо
  
  нц для i от 1 до количество_лучей*2
    угол := i*угловой_шаг
    
    если i mod 2 = 1 то
      | Внутренняя вершина
      сместиться в точку х_центра+внутренний_радиус*cos(угол), у_центра+внутренний_радиус*sin(угол)
    иначе
      | Внешняя вершина
      сместиться в точку х_центра+внешний_радиус*cos(угол), у_центра+внешний_радиус*sin(угол)
    все
  кц
  
  | Замыкаем контур
  сместиться в точку х_центра+внешний_радиус, у_центра
  
  поднять перо
кон
При разработке вспомогательных алгоритмов полезно учитывать позицию Чертёжника до и после выполнения алгоритма. Есть два распространённых подхода:

1. После завершения алгоритма возвращать Чертёжника в исходную позицию:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
алг квадрат_с_возвратом(х, у, сторона)
нач
  цел начальный_х, начальный_у
  начальный_х := Поз_Х()  | Сохраняем текущие координаты
  начальный_у := Поз_У()
  
  сместиться в точку х, у
  опустить перо
  нц для i от 1 до 4
    сместиться на вектор (сторона, 0)
    сместиться на вектор (0, сторона)
    сместиться на вектор (-сторона, 0)
    сместиться на вектор (0, -сторона)
  кц
  поднять перо
  
  сместиться в точку начальный_х, начальный_у  | Возвращаемся
кон
2. Завершать алгоритм в определённой точке, связанной с рисуемой фигурой (например, в её центре или правом верхнем углу):

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
алг квадрат_с_известным_окончанием(х, у, сторона)
нач
  сместиться в точку х, у
  опустить перо
  сместиться на вектор (сторона, 0)
  сместиться на вектор (0, сторона)
  сместиться на вектор (-сторона, 0)
  сместиться на вектор (0, -сторона)
  поднять перо
  
  | Заканчиваем в центре квадрата
  сместиться в точку х+сторона/2, у+сторона/2
кон
Оба подхода имеют свои преимущества. Первый удобен, когда алгоритмы вызываются последовательно из заранее заданных позиций. Второй полезен, когда следующее действие логически связано с только что нарисованной фигурой.
Рекурсивные вспомогательные алгоритмы открывают новые возможности для создания сложных структур. Например, фрактальное дерево:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
алг дерево(х, у, длина, угол, уровень)
| х, у - координаты начальной точки
| длина - длина ветви
| угол - угол наклона ветви
| уровень - глубина рекурсии
нач
  вещ новый_х, новый_у
  
  если уровень <= 0 то
    | Базовый случай - заканчиваем рекурсию
    выход
  все
  
  | Вычисляем координаты конца ветви
  новый_х := х + длина * cos(угол * pi / 180)
  новый_у := у + длина * sin(угол * pi / 180)
  
  | Рисуем ветвь
  сместиться в точку х, у
  опустить перо
  сместиться в точку новый_х, новый_у
  поднять перо
  
  | Рекурсивно рисуем правую и левую подветви
  дерево(новый_х, новый_у, длина*0.7, угол+30, уровень-1)
  дерево(новый_х, новый_у, длина*0.7, угол-30, уровень-1)
кон
Запустив этот алгоритм с параметрами `дерево(400, 100, 100, 90, 5)`, мы получим красивое симметричное дерево высотой 5 уровней.
Часто при разработке сложных алгоритмов я сталкивался с трудностью отлаживания рекурсивных структур. Один из эффективных приёмов — добавление отладочной информации, которая помогает понять текущее состояние:

Code
1
2
3
4
5
6
алг дерево_с_отладкой(х, у, длина, угол, уровень)
нач
  вывод "Уровень:", уровень, ", Координаты:", х, у, ", Длина:", длина, ", Угол:", угол
  
  | Далее идёт основной код алгоритма...
кон
При разработке библиотеки вспомогательных алгоритмов полезно группировать связанные функции. Например, можно создать семейство алгоритмов для работы с графиками функций:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
алг координатные_оси(х_мин, х_макс, у_мин, у_макс, шаг)
нач
  | Горизонтальная ось
  сместиться в точку х_мин, 0
  опустить перо
  сместиться в точку х_макс, 0
  поднять перо
  
  | Вертикальная ось
  сместиться в точку 0, у_мин
  опустить перо
  сместиться в точку 0, у_макс
  поднять перо
  
  | Метки на осях
  нц для х от х_мин до х_макс шаг шаг
    сместиться в точку х, -0.2
    опустить перо
    сместиться в точку х, 0.2
    поднять перо
  кц
  
  нц для у от у_мин до у_макс шаг шаг
    сместиться в точку -0.2, у
    опустить перо
    сместиться в точку 0.2, у
    поднять перо
  кц
кон
 
алг график_функции(функция, х_мин, х_макс, шаг)
| функция - строковое представление функции (для упрощения примера)
нач
  вещ х, у
  
  сместиться в точку х_мин, вычислить_значение(функция, х_мин)
  опустить перо
  
  нц для х от х_мин+шаг до х_макс шаг шаг
    у := вычислить_значение(функция, х)
    сместиться в точку х, у
  кц
  
  поднять перо
кон
Здесь вычислить_значение — это гипотетическая функция, которая принимает строковое представление функции и значение аргумента, а возвращает значение функции в этой точке. В реальном КуМире такой функции нет, но мы могли бы реализовать её для конкретных функций:

Code
1
2
3
4
5
6
7
8
9
10
алг вещ вычислить_значение(функция, х)
нач
  если функция = "синус" то
    рез := sin(х)
  иначе если функция = "парабола" то
    рез := х*х
  иначе
    рез := х  | Линейная функция по умолчанию
  все
кон
Ещё один полезный приём при работе с вспомогательными алгоритмами — создание оберток для упрощения интерфейса. Например, если в большинстве случаев нам нужно рисовать правильный многоугольник с центром в начале координат:

Code
1
2
3
4
алг правильный_многоугольник_простой(количество_сторон, радиус)
нач
  многоугольник(0, 0, радиус, количество_сторон)
кон
Такие обертки снижают количество параметров и делают код основного алгоритма более читаемым.
При создании сложных композиций часто бывает полезно отделить логику расположения элементов от их рисования. Например, для создания "деревни" из нескольких домиков:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
алг деревня(х_центра, у_центра, размер, количество_домов)
нач
  цел i
  вещ угол, расстояние, х_дома, у_дома, размер_дома
  
  | Распределяем дома по кругу вокруг центральной точки
  нц для i от 1 до количество_домов
    угол := 2*pi*i/количество_домов
    расстояние := размер*2
    
    х_дома := х_центра + расстояние*cos(угол)
    у_дома := у_центра + расстояние*sin(угол)
    
    | Размер дома случайный, от 60% до 100% базового размера
    размер_дома := размер * (0.6 + 0.4*random())
    
    | Рисуем дом
    дом_с_деталями(х_дома, у_дома, размер_дома, размер_дома*0.8)
  кц
кон

Решение задач на простые перемещения



Теперь, когда мы разобрались с базовыми принципами работы Чертёжника и алгоритмическими конструкциями, пришло время применить знания на практике. Начнём с решения простейших задач на перемещение и рисование элементарных фигур — это фундамент, без которого невозможно двигаться дальше.

Задача 1: Рисование прямоугольника



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

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
алг прямоугольник(x, y, ширина, высота)
нач
  сместиться в точку x, y
  опустить перо
  сместиться в точку x + ширина, y
  сместиться в точку x + ширина, y + высота
  сместиться в точку x, y + высота
  сместиться в точку x, y
  поднять перо
кон
 
алг основной
нач
  прямоугольник(2, 3, 5, 4)
кон
Обратите внимание, как мы двигаемся против часовой стрелки, последовательно обходя все вершины прямоугольника. Это простой пример, но он демонстрирует ключевой принцип работы Чертёжника — последовательное построение фигур по вершинам.

Задача 2: Координатная прямая



Нарисуем числовую ось с метками. Эта задача часто встречается при визуализации математических задач.

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
алг числовая_ось(начало, конец, шаг)
нач
  цел i
  
  | Рисуем основную линию
  сместиться в точку начало, 0
  опустить перо
  сместиться в точку конец, 0
  поднять перо
  
  | Рисуем метки
  нц для i от начало до конец шаг шаг
    сместиться в точку i, 0
    опустить перо
    сместиться в точку i, 0.5  | Длина метки
    поднять перо
  кц
кон
 
алг основной
нач
  числовая_ось(-10, 10, 1)
кон
Задача объединяет линейное перемещение с циклическим повторением, что делает её хорошим примером базового алгоритма.

Задача 3: Равносторонний треугольник



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

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
алг равносторонний_треугольник(x, y, сторона)
нач
  вещ высота
  
  высота := сторона * sqrt(3) / 2  | Высота треугольника
  
  сместиться в точку x, y
  опустить перо
  сместиться в точку x + сторона, y
  сместиться в точку x + сторона/2, y + высота
  сместиться в точку x, y
  поднять перо
кон
 
алг основной
нач
  равносторонний_треугольник(2, 3, 6)
кон
В этом решении мы используем формулу для вычисления высоты равностороннего треугольника. Такие математические расчёты часто необходимы при программировании Чертёжника.

Задача 4: Ломаная линия



Нарисуем произвольную ломаную линию, заданную последовательностью точек.

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
алг ломаная(количество_точек)
нач
  цел i
  вещ x, y
  
  | Перемещаемся в первую точку
  ввод x, y
  сместиться в точку x, y
  опустить перо
  
  | Последовательно проходим через все точки
  нц для i от 2 до количество_точек
    ввод x, y
    сместиться в точку x, y
  кц
  
  поднять перо
кон
 
алг основной
нач
  ломаная(5)  | Пользователь введёт 5 пар координат
кон
Этот алгоритм демонстрирует взаимодействие с пользователем для получения данных — важный аспект практического программирования.

Задача 5: "Колесо" из отрезков



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

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
алг колесо(x_центра, y_центра, радиус, количество_спиц)
нач
  цел i
  вещ угол
  
  нц для i от 1 до количество_спиц
    угол := 2 * PI * i / количество_спиц
    
    | Рисуем спицу
    сместиться в точку x_центра, y_центра
    опустить перо
    сместиться в точку x_центра + радиус * cos(угол), y_центра + радиус * sin(угол)
    поднять перо
  кц
кон
 
алг основной
нач
  колесо(10, 10, 8, 12)  | 12-спицевое колесо
кон
Эта задача вводит нас в мир параметрических уравнений и полярных координат — мощных инструментов для работы с Чертёжником.

Я помню свою первую попытку создать похожее "колесо". Тогда я попробовал рисовать спицы, перемещаясь от одного конца к другому через центр, но получил странную фигуру из-за того, что перо оставалось опущенным. Ключевой момент здесь — поднимать перо перед перемещением к началу новой спицы.

Практические советы для решения задач на перемещение



При работе с задачами на перемещение я выработал несколько полезных привычек:
1. Предварительный эскиз. Набросайте будущий рисунок на бумаге, обозначив ключевые координаты. Это помогает избежать логических ошибок.
2. Единый стиль перемещения. Выберите один подход (например, всегда двигаться против часовой стрелки при обходе фигур) и придерживайтесь его.
3. Проверка граничных случаев. Тестируйте свой алгоритм на экстремальных входных данных (очень маленькие или большие значения).
4. Модульность. Разбивайте сложные перемещения на серию простых.

Давайте рассмотрим еще несколько интересных задач, использующих изученные принципы.

Задача: Рисование звезды



Нарисуем пятиконечную звезду с заданным радиусом:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
алг пятиконечная_звезда(x_центра, y_центра, радиус)
нач
  цел i
  вещ угол, x_вершины, y_вершины
  цел вершины[5]
  
  | Запоминаем порядок обхода вершин для пятиконечной звезды
  вершины[0] := 0
  вершины[1] := 2
  вершины[2] := 4
  вершины[3] := 1
  вершины[4] := 3
  
  | Перемещаемся к первой вершине
  угол := 2 * PI * вершины[0] / 5 - PI/2  | Коррекция, чтобы верхняя точка смотрела вверх
  x_вершины := x_центра + радиус * cos(угол)
  y_вершины := y_центра + радиус * sin(угол)
  сместиться в точку x_вершины, y_вершины
  опустить перо
  
  | Обходим остальные вершины в нужном порядке
  нц для i от 1 до 4
    угол := 2 * PI * вершины[i] / 5 - PI/2
    x_вершины := x_центра + радиус * cos(угол)
    y_вершины := y_центра + радиус * sin(угол)
    сместиться в точку x_вершины, y_вершины
  кц
  
  | Замыкаем контур
  угол := 2 * PI * вершины[0] / 5 - PI/2
  x_вершины := x_центра + радиус * cos(угол)
  y_вершины := y_центра + радиус * sin(угол)
  сместиться в точку x_вершины, y_вершины
  
  поднять перо
кон
 
алг основной
нач
  пятиконечная_звезда(10, 10, 7)
кон
Ключевая особенность этой задачи — правильный порядок обхода вершин. Если просто последовательно обойти все вершины правильного пятиугольника, мы получим не звезду, а пятиугольник. Для звезды нам нужно перемещаться через одну вершину.
Однажды я целый вечер мучился над подобной задачей, пока не придумал использовать массив для задания порядка обхода вершин. Иногда самые простые решения приходят не сразу!

Задача: Сетка точек



Нарисуем сетку точек с заданным шагом:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
алг сетка_точек(x_начало, y_начало, ширина, высота, шаг)
нач
  цел i, j
  
  нц для i от 0 до ширина шаг шаг
    нц для j от 0 до высота шаг шаг
      | Рисуем точку как маленький крестик
      сместиться в точку x_начало + i - 0.1, y_начало + j
      опустить перо
      сместиться в точку x_начало + i + 0.1, y_начало + j
      поднять перо
      
      сместиться в точку x_начало + i, y_начало + j - 0.1
      опустить перо
      сместиться в точку x_начало + i, y_начало + j + 0.1
      поднять перо
    кц
  кц
кон
 
алг основной
нач
  сетка_точек(0, 0, 20, 15, 5)
кон
Этот алгоритм использует вложенные циклы для перебора точек в двумерном пространстве — важная техника для многих графических задач.

Современное программирование — это не только голый код, но и понимание структуры и эстетики. Аккуратно написанный алгоритм для Чертёжника часто создает визуально привлекательные результаты, что служит отличной мотивацией для начинающих программистов.

Техника создания координатных осей и сеток



Практически в любых серьёзных графических проектах с Чертёжником нам требуется система координат. Создание осей и координатных сеток — не просто служебный элемент, но основа, которая помогает ориентироваться на плоскости и делает дальнейшую работу значительно удобнее. Прежде всего рассмотрим алгоритм создания базовых координатных осей. Это не только упрощает отладку, но и помогает наглядно продемонстрировать положение объектов:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
алг координатные_оси(xMin, xMax, yMin, yMax)
нач
  | Ось X
  сместиться в точку xMin, 0
  опустить перо
  сместиться в точку xMax, 0
  поднять перо
  
  | Ось Y
  сместиться в точку 0, yMin
  опустить перо
  сместиться в точку 0, yMax
  поднять перо
кон
Такой минималистичный подход хорош для базовой ориентации, но на практике понадобится нечто большее. Добавим подписи осей и метки делений, чтобы сделать координатную систему более информативной:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
алг оси_с_делениями(xMin, xMax, yMin, yMax, шагДелений)
нач
  цел i
  
  | Рисуем основные оси
  координатные_оси(xMin, xMax, yMin, yMax)
  
  | Добавляем деления на оси X
  нц для i от xMin до xMax шаг шагДелений
    если i <> 0 то  | Пропускаем начало координат
      сместиться в точку i, -0.2
      опустить перо
      сместиться в точку i, 0.2
      поднять перо
    все
  кц
  
  | Добавляем деления на оси Y
  нц для i от yMin до yMax шаг шагДелений
    если i <> 0 то  | Пропускаем начало координат
      сместиться в точку -0.2, i
      опустить перо
      сместиться в точку 0.2, i
      поднять перо
    все
  кц
кон
На собственном опыте убедился, что простые метки делений иногда недостаточны, особенно когда работаешь со сложными графиками. Усовершенствуем алгоритм, добавив числовые подписи:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
алг оси_с_подписями(xMin, xMax, yMin, yMax, шагДелений)
нач
  цел i
  
  | Основные оси с делениями
  оси_с_делениями(xMin, xMax, yMin, yMax, шагДелений)
  
  | Здесь должны быть команды для вывода текстовых подписей
  | В системе КуМир это можно имитировать рисованием цифр
  | Для примера просто покажем местоположение подписей
  
  нц для i от xMin до xMax шаг шагДелений
    если i <> 0 то
      сместиться в точку i, -0.5
      | Тут в реальном коде был бы вывод числа i
    все
  кц
  
  нц для i от yMin до yMax шаг шагДелений
    если i <> 0 то
      сместиться в точку -0.7, i
      | Тут в реальном коде был бы вывод числа i
    все
  кц
кон
Когда мы переходим к построению графиков или более сложных геометрических фигур, часто необходима координатная сетка. Она значительно облегчает ориентацию и оценку расстояний:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
алг координатная_сетка(xMin, xMax, yMin, yMax, шагСетки)
нач
  цел i
  
  | Вертикальные линии
  нц для i от xMin до xMax шаг шагСетки
    сместиться в точку i, yMin
    опустить перо
    сместиться в точку i, yMax
    поднять перо
  кц
  
  | Горизонтальные линии
  нц для i от yMin до yMax шаг шагСетки
    сместиться в точку xMin, i
    опустить перо
    сместиться в точку xMax, i
    поднять перо
  кц
кон
В своей практике я заметил, что полная сетка иногда перегружает изображение. Хорошим компромиссом может быть полупрозрачная или пунктирная сетка. Реализовать пунктир в Чертёжнике можно так:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
алг пунктирная_линия(x1, y1, x2, y2, длинаШтриха, длинаПропуска)
нач
  вещ длина, доляШтриха, шагX, шагY
  цел i, колвоСегментов
  
  | Рассчитываем длину линии
  длина := sqrt((x2-x1)^2 + (y2-y1)^2)
  
  | Сколько сегментов (штрих+пропуск) поместится
  колвоСегментов := floor(длина / (длинаШтриха + длинаПропуска))
  
  | Доля пути, которую занимает штрих
  доляШтриха := длинаШтриха / (длинаШтриха + длинаПропуска)
  
  | Шаги по x и y для каждого сегмента
  шагX := (x2 - x1) / колвоСегментов
  шагY := (y2 - y1) / колвоСегментов
  
  нц для i от 0 до колвоСегментов-1
    | Начало сегмента
    сместиться в точку x1 + i*шагX, y1 + i*шагY
    
    | Рисуем штрих
    опустить перо
    сместиться в точку x1 + i*шагX + шагX*доляШтриха, y1 + i*шагY + шагY*доляШтриха
    поднять перо
  кц
кон
Используя функцию пунктирной линии, можно создать более изящную координатную сетку:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
алг пунктирная_сетка(xMin, xMax, yMin, yMax, шагСетки)
нач
  цел i
  
  | Вертикальные пунктирные линии
  нц для i от xMin до xMax шаг шагСетки
    если i <> 0 то  | Основные оси оставляем сплошными
      пунктирная_линия(i, yMin, i, yMax, 0.3, 0.2)
    все
  кц
  
  | Горизонтальные пунктирные линии
  нц для i от yMin до yMax шаг шагСетки
    если i <> 0 то  | Основные оси оставляем сплошными
      пунктирная_линия(xMin, i, xMax, i, 0.3, 0.2)
    все
  кц
  
  | Добавляем основные оси как сплошные линии
  координатные_оси(xMin, xMax, yMin, yMax)
кон
Помню, как в одном из своих проектов я столкнулся с необходимостью масштабировать координатную сетку в зависимости от диапазона значений. Вот полезная функция для автоматического определения оптимального шага сетки:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
алг вещ оптимальный_шаг(мин, макс, целевое_количество)
нач
  вещ диапазон, примерный_шаг, порядок, нормализованный_шаг
  
  диапазон := макс - мин
  примерный_шаг := диапазон / целевое_количество
  
  | Находим порядок величины
  порядок := floor(log10(примерный_шаг))
  
  | Нормализуем шаг до 1, 2 или 5 умноженных на степень 10
  нормализованный_шаг := примерный_шаг / (10^порядок)
  
  если нормализованный_шаг < 1.5 то
    рез := 10^порядок
  иначе если нормализованный_шаг < 3.5 то
    рез := 2 * 10^порядок
  иначе
    рез := 5 * 10^порядок
  все
кон
Иногда при построении графиков и диаграмм нужны логарифмические оси. Вот пример создания логарифмической оси X:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
алг логарифмическая_ось_x(xMin, xMax, yMin, yMax)
нач
  цел степень, i
  вещ x
  
  | Горизонтальная ось
  сместиться в точку xMin, 0
  опустить перо
  сместиться в точку xMax, 0
  поднять перо
  
  | Вертикальная ось (остается линейной)
  сместиться в точку 0, yMin
  опустить перо
  сместиться в точку 0, yMax
  поднять перо
  
  | Рисуем деления для каждой степени 10
  нц для степень от ceil(log10(xMin)) до floor(log10(xMax))
    x := 10^степень
    
    | Главная метка для степени
    сместиться в точку x, -0.3
    опустить перо
    сместиться в точку x, 0.3
    поднять перо
    
    | Промежуточные метки (2-9)
    нц для i от 2 до 9
      сместиться в точку i*x/10, -0.2
      опустить перо
      сместиться в точку i*x/10, 0.2
      поднять перо
    кц
  кц
кон
В моей практике создание правильной системы координат часто занимало больше времени, чем непосредственное рисование объектов! Но это оправданные усилия: хорошая сетка не только улучшает визуальное восприятие, но и значительно упрощает разработку и отладку последующих алгоритмов.

Научившись создавать качественные координатные системы, мы заложили отличную основу для дальнейшей работы с Чертёжником. Координатные оси и сетки — не просто вспомогательный элемент, а мощный инструмент, который поднимает наши графические проекты на новый уровень.

Относительное перемещение с использованием переменных



Относительное перемещение — одна из самых мощных возможностей Чертёжника, которая раскрывает свой потенциал при комбинировании с использованием переменных. Этот подход позволяет создавать масштабируемые и легко модифицируемые рисунки, а также значительно упрощает реализацию сложных геометрических построений.

В отличие от абсолютных координат, где мы точно указываем конечную точку перемещения, при относительном перемещении мы задаём вектор смещения от текущей позиции. Команда `сместиться на вектор (a, b)` перемещает Чертёжника на a единиц вправо и b единиц вверх относительно текущего положения.

Давайте рассмотрим, как использование переменных с относительным перемещением открывает новые возможности для программирования Чертёжника.

Задача 1: Масштабируемая снежинка



Создадим алгоритм для рисования симметричной снежинки с шестью лучами, размер которой можно легко менять:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
алг снежинка(центр_x, центр_y, размер)
нач
цел i
вещ угол, dx, dy
  
| Рисуем 6 лучей снежинки
нц для i от 0 до 5
  угол := i * PI / 3  | Лучи через каждые 60 градусов
  
  | Вычисляем вектор направления
  dx := размер * cos(угол)
  dy := размер * sin(угол)
  
  | Перемещаемся в центр
  сместиться в точку центр_x, центр_y
  опустить перо
  
  | Рисуем основной луч
  сместиться на вектор (dx, dy)
  поднять перо
  
  | Рисуем боковые ответвления
  сместиться на вектор (-dx/4, -dy/4)  | Возвращаемся на 1/4 назад по лучу
  опустить перо
  
  | Левое ответвление
  сместиться на вектор (dy/3, -dx/3)
  поднять перо
  
  | Возвращаемся к точке ответвления
  сместиться на вектор (-dy/3, dx/3)
  опустить перо
  
  | Правое ответвление
  сместиться на вектор (-dy/3, dx/3)
  поднять перо
кц
кон
 
алг основной
нач
  снежинка(10, 10, 6)  | Снежинка в точке (10, 10) с размером 6
  снежинка(25, 15, 3)  | Маленькая снежинка в другой позиции
кон
Ключевое преимущество данного решения в использовании переменных dx и dy для хранения компонентов вектора перемещения. Благодаря этому мы можем:
1. Легко масштабировать снежинку, изменяя параметр размер.
2. Рисовать боковые ответвления, используя компоненты основного луча с математическими преобразованиями.
3. Размещать снежинку в любой точке плоскости.

Задача 2: Спираль Архимеда



Спираль Архимеда — это красивая кривая, радиус которой равномерно увеличивается с углом поворота. Построим её с помощью относительного перемещения:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
алг спираль_архимеда(центр_x, центр_y, коэффициент, количество_оборотов)
нач
вещ угол, r, x_пред, y_пред, x_нов, y_нов, шаг_угла
  
шаг_угла := PI / 36  | Шаг 5 градусов для плавности
x_пред := центр_x
y_пред := центр_y
  
сместиться в точку x_пред, y_пред
опустить перо
  
нц для угол от 0 до 2 * PI * количество_оборотов шаг шаг_угла
  r := коэффициент * угол
  x_нов := центр_x + r * cos(угол)
  y_нов := центр_y + r * sin(угол)
    
  | Относительное перемещение вместо абсолютного
  сместиться на вектор (x_нов - x_пред, y_нов - y_пред)
    
  | Запоминаем текущую позицию для следующей итерации
  x_пред := x_нов
  y_пред := y_нов
кц
  
поднять перо
кон
 
алг основной
нач
спираль_архимеда(15, 15, 0.2, 3)  | Три оборота спирали
кон
В этом примере мы используем относительное перемещение для создания плавной кривой. Обратите внимание на технику: вместо постоянного перемещения в абсолютные координаты, мы вычисляем вектор смещения между предыдущей и новой точкой, что даёт более точный и эффективный результат.

Задача 3: Генератор случайного ландшафта



Создадим интересный эффект горного ландшафта, используя случайные смещения:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
алг случайный_ландшафт(начало_x, начало_y, длина, детализация, высота)
нач
цел i
вещ текущий_x, случайное_смещение
  
текущий_x := начало_x
сместиться в точку начало_x, начало_y
опустить перо
  
нц для i от 1 до длина шаг детализация
  | Случайное смещение по вертикали
  случайное_смещение := (random() * 2 - 1) * высота
  
  | Перемещаемся на фиксированный шаг вправо и случайный шаг вверх/вниз
  текущий_x := текущий_x + детализация
  сместиться на вектор (детализация, случайное_смещение)
кц
  
поднять перо
кон
 
алг основной
нач
случайный_ландшафт(5, 10, 50, 1, 0.5)   | Детальный, но низкий ландшафт
случайный_ландшафт(5, 20, 50, 2, 1.5)   | Менее детальный, но с высокими пиками
кон
Этот алгоритм использует относительное перемещение в сочетании со случайными числами для создания естественно выглядящего ландшафта. Параметры детализация и высота позволяют контролировать характер получаемого рисунка.

Задача 4: Циклоида



Циклоида — кривая, которую описывает точка на окружности, когда окружность катится по прямой без проскальзывания:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
алг циклоида(начало_x, высота, радиус, длина)
нач
вещ угол, x_пред, y_пред, x_нов, y_нов, шаг_угла
  
шаг_угла := PI / 20  | Для плавности кривой
угол := 0
x_пред := начало_x
y_пред := высота
  
сместиться в точку x_пред, y_пред
опустить перо
  
нц пока угол <= длина / радиус
  x_нов := начало_x + радиус * угол - радиус * sin(угол)
  y_нов := высота - радиус + радиус * cos(угол)
    
  | Относительное перемещение для плавности
  сместиться на вектор (x_нов - x_пред, y_нов - y_пред)
    
  | Запоминаем текущую позицию
  x_пред := x_нов
  y_пред := y_нов
    
  угол := угол + шаг_угла
кц
  
поднять перо
кон
 
алг основной
нач
циклоида(5, 15, 3, 30)
кон
Этот пример демонстрирует мощь параметрических уравнений в сочетании с относительным перемещением для создания сложных математических кривых.

Практические рекомендации для работы с относительным перемещением



Когда я начинал осваивать программирование Чертёжника, долго не мог понять, в каких случаях лучше использовать абсолютные координаты, а когда — относительные. Со временем выработал несколько правил:
1. Используйте относительное перемещение для:
- Создания регулярных структур и узоров.
- Параметрических кривых и спиралей.
- Фрактальных алгоритмов.
- Рисунков, которые должны масштабироваться без изменения кода.
2. Используйте абсолютное перемещение для:
- Фиксированных геометрических фигур.
- Рисования по заранее заданным точкам.
- Когда нужно точно контролировать положение Чертёжника.
3. Комбинируйте оба подхода:
- Используйте абсолютное перемещение для установки начальной позиции.
- Для дальнейшего рисования применяйте относительное перемещение.

Вот пример алгоритма, сочетающего оба подхода для создания орнамента из шестерёнок:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
алг шестеренка(центр_x, центр_y, внешний_радиус, количество_зубцов)
нач
цел i
вещ угловой_шаг, внутренний_радиус, угол
вещ dx, dy, dx_пред, dy_пред
  
внутренний_радиус := внешний_радиус * 0.8
угловой_шаг := 2 * PI / количество_зубцов
  
| Перемещаемся в начальную точку (абсолютное перемещение)
угол := 0
dx := внешний_радиус * cos(угол)
dy := внешний_радиус * sin(угол)
сместиться в точку центр_x + dx, центр_y + dy
опустить перо
  
dx_пред := dx
dy_пред := dy
  
| Рисуем шестеренку (относительное перемещение)
нц для i от 1 до количество_зубцов
  | Внутренний радиус
  угол := угол + угловой_шаг / 3
  dx := внутренний_радиус * cos(угол)
  dy := внутренний_радиус * sin(угол)
  сместиться на вектор (dx - dx_пред, dy - dy_пред)
  dx_пред := dx
  dy_пред := dy
    
  | Внешний радиус (зубец)
  угол := угол + угловой_шаг / 3
  dx := внешний_радиус * cos(угол)
  dy := внешний_радиус * sin(угол)
  сместиться на вектор (dx - dx_пред, dy - dy_пред)
  dx_пред := dx
  dy_пред := dy
    
  | Снова внутренний радиус
  угол := угол + угловой_шаг / 3
  dx := внутренний_радиус * cos(угол)
  dy := внутренний_радиус * sin(угол)
  сместиться на вектор (dx - dx_пред, dy - dy_пред)
  dx_пред := dx
  dy_пред := dy
кц
  
| Замыкаем контур, возвращаясь к начальной точке
сместиться в точку центр_x + внешний_радиус, центр_y
поднять перо
кон
 
алг орнамент_из_шестеренок(количество, радиус)
нач
цел i
вещ угол, x, y
  
нц для i от 1 до количество
  угол := 2 * PI * i / количество
  x := 15 + 10 * cos(угол)
  y := 15 + 10 * sin(угол)
  шестеренка(x, y, радиус, 10 + i mod 4)
кц
кон
 
алг основной
нач
орнамент_из_шестеренок(5, 3)
кон
Использование переменных для хранения промежуточных координат в этом примере позволяет нам создать плавную кривую и избежать накопления ошибок округления, которые могли бы привести к неточностям при рисовании.

Овладение техникой относительного перемещения с использованием переменных открывает практически безграничные возможности при работе с Чертёжником. Этот подход не только делает код более читаемым и поддерживаемым, но и позволяет создавать алгоритмы, которые можно легко масштабировать, модифицировать и адаптировать для различных задач.

Рисование базовых геометрических фигур



После освоения простых перемещений и работы с координатами перейдем к созданию базовых геометрических фигур. Это фундамент для более сложных графических проектов в Чертёжнике. Сейчас мы разберем несколько задач, которые помогут освоить основные приёмы рисования многоугольников и окружностей.

Задача 6: Правильный шестиугольник



Правильные многоугольники — частая задача в работе с Чертёжником. Рассмотрим алгоритм рисования правильного шестиугольника:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
алг шестиугольник(центр_x, центр_y, радиус)
нач
цел i
вещ угол
 
| Перемещаемся к первой вершине
угол := 0
сместиться в точку центр_x + радиус * cos(угол), центр_y + радиус * sin(угол)
опустить перо
 
| Рисуем последовательно все вершины
нц для i от 1 до 6
  угол := 2 * PI * i / 6
  сместиться в точку центр_x + радиус * cos(угол), центр_y + радиус * sin(угол)
кц
 
поднять перо
кон
 
алг основной
нач
шестиугольник(10, 10, 5)
кон
Алгоритм использует параметрические уравнения для расчёта координат вершин. Главное преимущество такого подхода — он легко адаптируется для любого правильного многоугольника, просто изменив количество вершин.

Задача 7: Пятиконечная звезда



Звёзды — интересный тип фигур, требующий нетривиального порядка соединения вершин:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
алг пятиконечная_звезда(центр_x, центр_y, радиус)
нач
цел i, индекс
цел порядок[] | Задает порядок обхода вершин
вещ угол
 
| Инициализируем порядок обхода вершин
порядок[0] := 0
порядок[1] := 2
порядок[2] := 4
порядок[3] := 1
порядок[4] := 3
 
| Перемещаемся к первой вершине
угол := 2 * PI * порядок[0] / 5 - PI/2 | Поправка для вертикальной ориентации
сместиться в точку центр_x + радиус * cos(угол), центр_y + радиус * sin(угол)
опустить перо
 
| Рисуем звезду, соединяя вершины в правильном порядке
нц для i от 1 до 4
  индекс := порядок[i]
  угол := 2 * PI * индекс / 5 - PI/2
  сместиться в точку центр_x + радиус * cos(угол), центр_y + радиус * sin(угол)
кц
 
| Замыкаем контур
угол := 2 * PI * порядок[0] / 5 - PI/2
сместиться в точку центр_x + радиус * cos(угол), центр_y + радиус * sin(угол)
 
поднять перо
кон
 
алг основной
нач
пятиконечная_звезда(10, 10, 6)
кон
Ключевой момент этого алгоритма — массив порядок, определяющий последовательность соединения вершин. Для пятиконечной звезды мы соединяем вершины правильного пятиугольника через одну.

Задача 8: Круг через аппроксимацию



В школьной системе КуМир нет встроенной команды для рисования окружностей, но мы можем аппроксимировать круг многоугольником с большим количеством сторон:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
алг круг(центр_x, центр_y, радиус)
нач
цел i
вещ угол, шаг
 
шаг := 2 * PI / 36 | 36 сегментов для аппроксимации (10 градусов)
 
| Перемещаемся к начальной точке
сместиться в точку центр_x + радиус, центр_y
опустить перо
 
| Рисуем окружность как 36-угольник
нц для угол от шаг до 2*PI шаг шаг
  сместиться в точку центр_x + радиус * cos(угол), центр_y + радиус * sin(угол)
кц
 
поднять перо
кон
 
алг основной
нач
круг(15, 15, 7)
кон
Чем больше сегментов мы используем (т.е. чем меньше шаг), тем более гладкой выглядит окружность. Это базовый принцип аппроксимации кривых в компьютерной графике.

Задача 9: Эллипс



Эллипс — это обобщение круга с двумя радиусами. Алгоритм его рисования очень похож на алгоритм рисования круга:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
алг эллипс(центр_x, центр_y, радиус_x, радиус_y)
нач
цел i
вещ угол, шаг
 
шаг := 2 * PI / 36
 
| Перемещаемся к начальной точке
сместиться в точку центр_x + радиус_x, центр_y
опустить перо
 
| Рисуем эллипс
нц для угол от шаг до 2*PI шаг шаг
  сместиться в точку центр_x + радиус_x * cos(угол), центр_y + радиус_y * sin(угол)
кц
 
поднять перо
кон
 
алг основной
нач
эллипс(12, 8, 6, 4) | Эллипс с горизонтальной полуосью 6 и вертикальной 4
кон
Эллипс — отличный пример того, как небольшое изменение алгоритма (разные радиусы по X и Y) даёт существенно иной визуальный результат.

Задача 10: Прямоугольник с закруглёнными углами



Сочетая прямоугольники и фрагменты окружностей, мы можем создавать более сложные формы:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
алг закругленный_прямоугольник(x, y, ширина, высота, радиус)
нач
вещ угол, шаг
 
шаг := PI / 18 | 20 градусов
 
| Проверяем, чтобы радиус не превышал половины меньшей стороны
если радиус > min(ширина/2, высота/2) то
  радиус := min(ширина/2, высота/2)
все
 
| Правый нижний угол
сместиться в точку x + ширина - радиус, y
опустить перо
нц для угол от 0 до PI/2 шаг шаг
  сместиться в точку x + ширина - радиус + радиус*cos(угол), y + радиус - радиус*sin(угол)
кц
 
| Правый верхний угол
сместиться в точку x + ширина, y + высота - радиус
нц для угол от PI/2 до PI шаг шаг
  сместиться в точку x + ширина - радиус + радиус*cos(угол), y + высота - радиус + радиус*sin(угол)
кц
 
| Левый верхний угол
сместиться в точку x + радиус, y + высота
нц для угол от PI до PI*3/2 шаг шаг
  сместиться в точку x + радиус + радиус*cos(угол), y + высота - радиус + радиус*sin(угол)
кц
 
| Левый нижний угол
сместиться в точку x, y + радиус
нц для угол от PI*3/2 до PI*2 шаг шаг
  сместиться в точку x + радиус + радиус*cos(угол), y + радиус + радиус*sin(угол)
кц
 
| Замыкаем контур
сместиться в точку x + ширина - радиус, y
 
поднять перо
кон
 
алг основной
нач
закругленный_прямоугольник(5, 5, 10, 6, 2)
кон
Этот пример отлично демонстрирует композицию — создание сложных форм из простых элементов. Прямоугольник с закруглёнными углами мы рисуем как комбинацию прямых линий и четвертей окружности.

Однажды я столкнулся с задачей нарисовать множество закругленных прямоугольников разного размера. Код получался громоздким, пока я не додумался параметризовать всё через одну функцию. Это позволило мне создать десятки таких фигур буквально в несколько строк кода.

Универсальный алгоритм для правильных многоугольников



Для рисования любого правильного многоугольника можно использовать единый алгоритм:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
алг правильный_многоугольник(центр_x, центр_y, радиус, число_сторон)
нач
цел i
вещ угол
 
| Проверка корректности входных данных
если число_сторон < 3 то число_сторон := 3 все
 
| Перемещаемся к первой вершине
угол := 0
сместиться в точку центр_x + радиус * cos(угол), центр_y + радиус * sin(угол)
опустить перо
 
| Рисуем многоугольник
нц для i от 1 до число_сторон
  угол := 2 * PI * i / число_сторон
  сместиться в точку центр_x + радиус * cos(угол), центр_y + радиус * sin(угол)
кц
 
поднять перо
кон
 
алг основной
нач
| Примеры использования - треугольник, квадрат, восьмиугольник
правильный_многоугольник(5, 5, 3, 3)
правильный_многоугольник(15, 5, 3, 4)
правильный_многоугольник(5, 15, 3, 8)
кон
Разработка таких универсальных алгоритмов — хорошая практика программирования, позволяющая сократить объем кода и повысить его переиспользуемость.

Помни, что геометрические фигуры — это базовые строительные блоки для более сложных изображений. Освоив их, ты сможешь комбинировать их для создания практически любых рисунков. В следующем разделе мы рассмотрим методы создания симметричных фигур и отражений, что ещё больше расширит твои возможности в работе с Чертёжником.

Создание симметричных фигур и отражений



Симметрия — один из самых мощных инструментов в арсенале Чертёжника. Используя симметричные конструкции, мы можем значительно упростить программы и создать более эстетичные изображения. В этом разделе мы рассмотрим различные типы симметрии и способы их реализации. Существует несколько основных видов симметрии: осевая (зеркальная), центральная и поворотная. Каждый тип имеет свои особенности и применения. Начнём с осевой симметрии, как наиболее интуитивно понятной.

Осевая симметрия



При осевой симметрии каждая точка фигуры имеет зеркальное отражение относительно некоторой оси. Для реализации такой симметрии в Чертёжнике нам нужно преобразовать координаты:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
алг отражение_по_оси_x(фигура, центр_x)
| Отражает фигуру относительно вертикальной оси x = центр_x
нач
| Сначала рисуем исходную фигуру
фигура()
 
| Затем рисуем её отражение
нц пока не конец алгоритма фигура
  | Для каждой команды перемещения в исходном алгоритме
  | меняем x-координату по формуле: x' = 2*центр_x - x
  | y-координата остаётся без изменений
кц
кон
Конечно, в КуМире нет возможности напрямую манипулировать командами другого алгоритма. На практике нам придётся либо дублировать код с изменением координат, либо параметризовать алгоритм для поддержки отражения. Рассмотрим второй подход:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
алг полумесяц(центр_x, центр_y, радиус, отражение)
| отражение: 1 для обычного рисования, -1 для отражения
нач
цел i
вещ угол, x, y
 
| Рисуем дугу
сместиться в точку центр_x + радиус * отражение, центр_y
опустить перо
нц для угол от 0 до PI шаг PI/20
  x := центр_x + радиус * cos(угол) * отражение
  y := центр_y + радиус * sin(угол)
  сместиться в точку x, y
кц
поднять перо
кон
 
алг симметричный_узор
нач
| Рисуем полумесяц и его отражение
полумесяц(10, 10, 5, 1)   | Обычное рисование
полумесяц(10, 10, 5, -1)  | Отражённое рисование
кон
Обратите внимание: для создания отражения относительно вертикальной оси мы просто меняем знак x-компоненты, а для отражения относительно горизонтальной оси — знак y-компоненты.

Практическая задача: Бабочка с симметричными крыльями



Создадим фигуру бабочки, используя осевую симметрию:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
алг крыло(центр_x, центр_y, размер, зеркально)
| зеркально: 1 для правого крыла, -1 для левого
нач
вещ множитель
 
множитель := зеркально  | Определяет направление
 
| Рисуем контур крыла
сместиться в точку центр_x, центр_y
опустить перо
сместиться на вектор (множитель * размер * 0.7, размер * 0.3)
сместиться на вектор (множитель * размер * 0.3, размер * 0.5)
сместиться на вектор (множитель * размер * -0.2, размер * 0.2)
сместиться на вектор (множитель * размер * -0.8, размер * -0.3)
сместиться на вектор (множитель * размер * 0.0, размер * -0.7)
сместиться в точку центр_x, центр_y
поднять перо
кон
 
алг бабочка(x, y, размер)
нач
| Рисуем тело
сместиться в точку x, y - размер * 0.5
опустить перо
сместиться в точку x, y + размер * 0.5
поднять перо
 
| Рисуем крылья
крыло(x, y, размер, 1)    | Правое крыло
крыло(x, y, размер, -1)   | Левое крыло
кон
 
алг основной
нач
бабочка(10, 10, 6)
кон
Здесь мы реализовали симметрию, используя параметр зеркально, который меняет знак x-компонентов в векторах перемещения.

Центральная симметрия



Центральная симметрия означает, что для каждой точки фигуры существует противоположная точка, равноудаленная от центра симметрии, но находящаяся в противоположном направлении.

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
алг центрально_симметричная_фигура(центр_x, центр_y, размер)
нач
цел i
вещ угол, радиус
 
| Рисуем лепесток
нц для угол от 0 до PI/3 шаг PI/30
  радиус := размер * (1 - 0.3 * sin(угол * 6))
  сместиться в точку центр_x + радиус * cos(угол), центр_y + радиус * sin(угол)
  если угол = 0 то опустить перо все
кц
поднять перо
 
| Используем центральную симметрию для рисования противоположного лепестка
нц для угол от 0 до PI/3 шаг PI/30
  радиус := размер * (1 - 0.3 * sin(угол * 6))
  сместиться в точку центр_x - радиус * cos(угол), центр_y - радиус * sin(угол)
  если угол = 0 то опустить перо все
кц
поднять перо
кон
Для центральной симметрии координаты преобразуются по формулам: x' = 2*центр_x - x, y' = 2*центр_y - y, что эквивалентно инверсии обеих координат относительно центра.

Поворотная симметрия



Поворотная симметрия подразумевает, что фигура выглядит одинаково при повороте на определённый угол вокруг центра. Это очень полезный тип симметрии для создания снежинок, звёзд и других радиально-симметричных узоров.

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
алг лепесток(центр_x, центр_y, длина, угол_поворота)
нач
вещ конечный_x, конечный_y
 
| Вычисляем конечную точку с учётом поворота
конечный_x := центр_x + длина * cos(угол_поворота)
конечный_y := центр_y + длина * sin(угол_поворота)
 
| Рисуем лепесток как изогнутую линию
сместиться в точку центр_x, центр_y
опустить перо
сместиться в точку центр_x + 0.5 * длина * cos(угол_поворота + PI/6), 
              центр_y + 0.5 * длина * sin(угол_поворота + PI/6)
сместиться в точку конечный_x, конечный_y
поднять перо
кон
 
алг цветок(центр_x, центр_y, размер, количество_лепестков)
нач
цел i
вещ угол
 
нц для i от 0 до количество_лепестков - 1
  угол := 2 * PI * i / количество_лепестков
  лепесток(центр_x, центр_y, размер, угол)
кц
кон
 
алг основной
нач
цветок(10, 10, 5, 8)  | Цветок с 8 лепестками
кон
В этом алгоритме мы создаём поворотную симметрию, вычисляя угол для каждого лепестка и применяя тригонометрические функции для определения координат.

Комбинированная симметрия и узоры



На практике часто применяются комбинации различных типов симметрии. Например, давайте создадим орнамент с использованием как осевой, так и поворотной симметрии:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
алг узорный_элемент(центр_x, центр_y, размер, угол)
нач
вещ x1, y1, x2, y2, x3, y3
 
| Вычисляем координаты трёх вершин треугольника с учётом поворота
x1 := центр_x + размер * cos(угол)
y1 := центр_y + размер * sin(угол)
x2 := центр_x + размер * cos(угол + 2*PI/3)
y2 := центр_y + размер * sin(угол + 2*PI/3)
x3 := центр_x + размер * cos(угол + 4*PI/3)
y3 := центр_y + размер * sin(угол + 4*PI/3)
 
| Рисуем треугольник
сместиться в точку x1, y1
опустить перо
сместиться в точку x2, y2
сместиться в точку x3, y3
сместиться в точку x1, y1
поднять перо
кон
 
алг сложный_узор(центр_x, центр_y, внешний_размер, внутренний_размер)
нач
цел i
вещ угол
 
| Внешний круг элементов (поворотная симметрия)
нц для i от 0 до 5
  угол := 2 * PI * i / 6
  узорный_элемент(центр_x, центр_y, внешний_размер, угол)
кц
 
| Внутренний круг элементов (повёрнутый относительно внешнего)
нц для i от 0 до 5
  угол := 2 * PI * i / 6 + PI/6  | Смещение на 30 градусов
  узорный_элемент(центр_x, центр_y, внутренний_размер, угол)
кц
кон
 
алг основной
нач
сложный_узор(15, 15, 7, 4)
кон
В процессе работы с симметрией я заметил интересную вещь: иногда намеренное нарушение симметрии создает более живое и привлекательное изображение. Симметрия — это инструмент, а не самоцель.

Например, можно создать почти симметричную фигуру с небольшими вариациями:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
алг почти_симметричный_узор(центр_x, центр_y, размер)
нач
цел i
вещ угол, вариация
 
нц для i от 0 до 7
  угол := 2 * PI * i / 8
  | Добавляем небольшое случайное отклонение
  вариация := 0.85 + random() * 0.3  | От 0.85 до 1.15
  
  | Рисуем "почти симметричный" элемент
  сместиться в точку центр_x, центр_y
  опустить перо
  сместиться в точку центр_x + размер * вариация * cos(угол), 
                центр_y + размер * вариация * sin(угол)
  поднять перо
кц
кон
Такой приём создает более органичное изображение, которое сохраняет общую структуру симметрии, но выглядит менее механическим.

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

Масштабирование изображений в среде КуМир



Масштабирование — один из ключевых приёмов в программировании графики, который позволяет менять размер изображений, сохраняя их пропорции и структуру. В Чертёжнике эта возможность открывает новые горизонты для создания динамических и адаптируемых иллюстраций. Представьте, что вы создали сложный рисунок и хотите его уменьшить, увеличить или даже исказить, растянув по одной из осей. Вместо того чтобы переписывать весь алгоритм с новыми координатами, можно использовать масштабирование, которое автоматически пересчитает все точки.

Основная идея масштабирования заключается в умножении координат на коэффициенты масштаба. Для равномерного масштабирования эти коэффициенты одинаковы для обеих осей, а для неравномерного — различаются. Рассмотрим простой пример масштабирования прямоугольника:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
алг масштабируемый_прямоугольник(x, y, ширина, высота, масштаб)
нач
сместиться в точку x, y
опустить перо
сместиться на вектор (ширина * масштаб, 0)
сместиться на вектор (0, высота * масштаб)
сместиться на вектор (-ширина * масштаб, 0)
сместиться на вектор (0, -высота * масштаб)
поднять перо
кон
 
алг основной
нач
масштабируемый_прямоугольник(5, 5, 4, 3, 1)    | Обычный размер
масштабируемый_прямоугольник(15, 5, 4, 3, 0.5)  | Уменьшенный вдвое
масштабируемый_прямоугольник(5, 12, 4, 3, 2)    | Увеличенный вдвое
кон
Для более сложных фигур логика та же, но применяется ко всем координатам. Вот пример масштабируемой звезды:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
алг масштабируемая_звезда(центр_x, центр_y, размер, масштаб)
нач
вещ внешний_радиус, внутренний_радиус
цел i
вещ угол
 
внешний_радиус := размер * масштаб
внутренний_радиус := размер * масштаб * 0.4
 
сместиться в точку центр_x + внешний_радиус, центр_y
опустить перо
 
нц для i от 1 до 10
  угол := i * PI / 5
  
  если i mod 2 = 1 то
    | Внутренняя вершина
    сместиться в точку центр_x + внутренний_радиус * cos(угол), 
                  центр_y + внутренний_радиус * sin(угол)
  иначе
    | Внешняя вершина
    сместиться в точку центр_x + внешний_радиус * cos(угол), 
                  центр_y + внешний_радиус * sin(угол)
  все
кц
 
поднять перо
кон
Более интересный случай — неравномерное масштабирование, когда коэффициенты масштаба по осям X и Y различны. Это позволяет создавать эффекты растяжения или сжатия:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
алг искаженный_круг(центр_x, центр_y, радиус, масштаб_x, масштаб_y)
нач
вещ угол, шаг
 
шаг := 2 * PI / 36
 
сместиться в точку центр_x + радиус * масштаб_x, центр_y
опустить перо
 
нц для угол от шаг до 2*PI шаг шаг
  сместиться в точку центр_x + радиус * cos(угол) * масштаб_x, 
                центр_y + радиус * sin(угол) * масштаб_y
кц
 
поднять перо
кон
 
алг основной
нач
искаженный_круг(10, 10, 5, 1, 1)     | Обычный круг
искаженный_круг(25, 10, 5, 1, 0.5)   | Сплющенный по вертикали
искаженный_круг(10, 25, 5, 0.5, 1.5)  | Сплющенный по горизонтали и вытянутый по вертикали
кон
При работе с более сложными рисунками удобно создать функцию масштабирования, которая будет применяться к отдельным частям рисунка. Например, при рисовании пейзажа объекты на переднем плане могут быть крупнее, а на заднем — мельче:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
алг домик(x, y, размер, масштаб)
нач
вещ ширина, высота
 
ширина := 4 * размер * масштаб
высота := 3 * размер * масштаб
 
| Стены
сместиться в точку x, y
опустить перо
сместиться на вектор (ширина, 0)
сместиться на вектор (0, высота)
сместиться на вектор (-ширина, 0)
сместиться на вектор (0, -высота)
поднять перо
 
| Крыша
сместиться в точку x, y + высота
опустить перо
сместиться на вектор (ширина/2, высота/2)
сместиться на вектор (ширина/2, -высота/2)
поднять перо
 
| Дверь
сместиться в точку x + ширина*0.4, y
опустить перо
сместиться на вектор (0, высота*0.6)
сместиться на вектор (ширина*0.2, 0)
сместиться на вектор (0, -высота*0.6)
сместиться на вектор (-ширина*0.2, 0)
поднять перо
кон
 
алг пейзаж_с_перспективой
нач
| Задний план (маленькие домики)
домик(2, 2, 1, 0.5)
домик(7, 3, 1, 0.4)
домик(12, 2, 1, 0.3)
 
| Передний план (крупный домик)
домик(15, 5, 1, 2)
кон
Одна из самых интересных техник — анимация с изменением масштаба. В КуМире нет встроенной анимации, но мы можем имитировать её, создавая последовательность кадров с увеличивающимся масштабом:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
алг пульсирующая_звезда(центр_x, центр_y, базовый_размер, шагов)
нач
цел i
вещ масштаб
 
нц для i от 1 до шагов
  | Вычисляем масштаб для текущего кадра
  масштаб := 1 + 0.5 * sin(i * 2 * PI / шагов)
  
  | Очищаем предыдущий кадр (в реальном КуМире нужно использовать специальные функции)
  
  | Рисуем звезду с новым масштабом
  масштабируемая_звезда(центр_x, центр_y, базовый_размер, масштаб)
  
  | Задержка для анимации (в реальном КуМире нужно использовать специальные функции)
кц
кон
В своей практике я часто использовал масштабирование для создания фракталов, когда одна и та же фигура повторяется в различных размерах:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
алг фрактальный_узор(x, y, размер, уровень)
нач
| Базовый случай — рисуем простой квадрат
если уровень <= 1 то
сместиться в точку x, y
опустить перо
сместиться на вектор (размер, 0)
сместиться на вектор (0, размер)
сместиться на вектор (-размер, 0)
сместиться на вектор (0, -размер)
поднять перо
выход
все
 
| Рисуем квадрат текущего уровня
сместиться в точку x, y
опустить перо
сместиться на вектор (размер, 0)
сместиться на вектор (0, размер)
сместиться на вектор (-размер, 0)
сместиться на вектор (0, -размер)
поднять перо
 
| Рекурсивно рисуем 4 уменьшенных узора в углах
фрактальный_узор(x + размер*0.1, y + размер*0.1, размер*0.4, уровень-1)
фрактальный_узор(x + размер*0.5, y + размер*0.1, размер*0.4, уровень-1)
фрактальный_узор(x + размер*0.1, y + размер*0.5, размер*0.4, уровень-1)  
фрактальный_узор(x + размер*0.5, y + размер*0.5, размер*0.4, уровень-1)
кон
Ещё один полезный приём — создание функции масштабирования координат, которая централизованно применяется ко всем точкам:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
алг вещ масштабировать_x(x, центр_x, масштаб)
нач
рез := центр_x + (x - центр_x) * масштаб
кон
 
алг вещ масштабировать_y(y, центр_y, масштаб)
нач
рез := центр_y + (y - центр_y) * масштаб
кон
 
алг масштабируемый_рисунок(центр_x, центр_y, масштаб)
нач
вещ x1, y1, x2, y2
 
| Оригинальные координаты
x1 := 10
y1 := 10
x2 := 15
y2 := 15
 
| Масштабируем координаты относительно центра
сместиться в точку масштабировать_x(x1, центр_x, масштаб), 
              масштабировать_y(y1, центр_y, масштаб)
опустить перо
сместиться в точку масштабировать_x(x2, центр_x, масштаб), 
              масштабировать_y(y2, центр_y, масштаб)
поднять перо
кон
Такой подход позволяет масштабировать изображение относительно произвольной точки (центра масштабирования), а не только начала координат. Освоив техники масштабирования, вы сможете создавать сложные динамические иллюстрации, где одни и те же элементы повторяются в разных размерах, создавая эффекты перспективы, фракталы и другие интересные визуальные эффекты.

В обучении программированию начинающих разработчиков я всегда подчёркиваю важность масштабирования как ключевой концепции не только для графики, но и для проектирования алгоритмов в целом. Умение написать код, который легко адаптируется к различным размерам и пропорциям — признак зрелого программиста.

Алгоритмы создания орнаментов и узоров



Орнаменты и узоры — одни из самых увлекательных задач для Чертёжника. Создание повторяющихся элементов и сложных декоративных композиций не только выглядит эффектно, но и развивает алгоритмическое мышление. Перейдём к разбору конкретных задач по созданию орнаментов с использованием цикличности и математических закономерностей.

Задача 11: Геометрический бордюр



Создадим простой бордюр из чередующихся геометрических фигур:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
алг геометрический_бордюр(x_начало, y, длина, количество_элементов)
нач
цел i
вещ шаг, размер
 
шаг := длина / количество_элементов
размер := шаг * 0.8  | Оставляем небольшие промежутки
 
нц для i от 0 до количество_элементов - 1
  если i mod 3 = 0 то
    | Рисуем квадрат
    сместиться в точку x_начало + i*шаг, y
    опустить перо
    сместиться на вектор (размер, 0)
    сместиться на вектор (0, размер)
    сместиться на вектор (-размер, 0)
    сместиться на вектор (0, -размер)
    поднять перо
  иначе если i mod 3 = 1 то
    | Рисуем треугольник
    сместиться в точку x_начало + i*шаг, y
    опустить перо
    сместиться на вектор (размер, 0)
    сместиться на вектор (-размер/2, размер)
    сместиться на вектор (-размер/2, -размер)
    поднять перо
  иначе
    | Рисуем ромб
    сместиться в точку x_начало + i*шаг + размер/2, y
    опустить перо
    сместиться на вектор (размер/2, размер/2)
    сместиться на вектор (-размер/2, размер/2)
    сместиться на вектор (-размер/2, -размер/2)
    сместиться на вектор (размер/2, -размер/2)
    поднять перо
  все
кц
кон
 
алг основной
нач
геометрический_бордюр(2, 5, 30, 10)
кон
Ключевой момент в создании бордюров — равномерное распределение элементов и организация чередования разных фигур, что достигается с помощью операции деления по модулю.

Задача 12: Волнистый орнамент



Создадим волнистый узор, комбинируя синусоиду с декоративными элементами:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
алг волнистый_орнамент(x_начало, y_средняя, длина, амплитуда, периоды)
нач
цел i
вещ шаг, x, y, угол
  
шаг := 0.5  | Шаг для плавности волны
  
| Рисуем основную волнистую линию
сместиться в точку x_начало, y_средняя
опустить перо
 
нц для x от x_начало до x_начало + длина шаг шаг
  угол := (x - x_начало) / длина * 2 * PI * периоды
  y := y_средняя + амплитуда * sin(угол)
  сместиться в точку x, y
кц
поднять перо
 
| Добавляем декоративные элементы на гребнях волн
нц для i от 0 до периоды - 1
  x := x_начало + длина * (i + 0.25) / периоды
  y := y_средняя + амплитуда
  
  | Рисуем круглое украшение
  сместиться в точку x, y
  опустить перо
  нц для угол от 0 до 2*PI шаг PI/10
    сместиться в точку x + амплитуда*0.2*cos(угол), y + амплитуда*0.2*sin(угол)
  кц
  поднять перо
  
  | Рисуем украшение во впадине
  x := x_начало + длина * (i + 0.75) / периоды
  y := y_средняя - амплитуда
  
  сместиться в точку x-амплитуда*0.2, y
  опустить перо
  сместиться в точку x+амплитуда*0.2, y
  поднять перо
  
  сместиться в точку x, y-амплитуда*0.2
  опустить перо
  сместиться в точку x, y+амплитуда*0.2
  поднять перо
кц
кон
 
алг основной
нач
волнистый_орнамент(2, 10, 30, 3, 4)
кон
Этот орнамент сочетает плавную базовую линию с декоративными элементами в характерных точках (максимумы и минимумы синусоиды). Такой подход можно использовать для создания различных декоративных бордюров.

Задача 13: Кельтский узор



Кельтские узоры известны своими переплетениями. Создадим упрощенную версию такого узора:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
алг кельтское_переплетение(центр_x, центр_y, размер, количество_петель)
нач
цел i
вещ угол, внешний_радиус, внутренний_радиус, средний_радиус
вещ x1, y1, x2, y2, x3, y3, x4, y4
 
внешний_радиус := размер
средний_радиус := размер * 0.8
внутренний_радиус := размер * 0.6
 
нц для i от 0 до количество_петель - 1
  угол := 2 * PI * i / количество_петель
  
  | Внешняя дуга
  сместиться в точку центр_x + внешний_радиус * cos(угол), центр_y + внешний_радиус * sin(угол)
  опустить перо
  
  нц для угол_дуги от угол до угол + PI / количество_петель шаг PI / (количество_петель * 10)
    сместиться в точку центр_x + внешний_радиус * cos(угол_дуги), 
                    центр_y + внешний_радиус * sin(угол_дуги)
  кц
  поднять перо
  
  | Внутренняя дуга (с противоположной стороны)
  угол := угол + PI
  
  сместиться в точку центр_x + внутренний_радиус * cos(угол), 
                центр_y + внутренний_радиус * sin(угол)
  опустить перо
  
  нц для угол_дуги от угол до угол + PI / количество_петель шаг PI / (количество_петель * 10)
    сместиться в точку центр_x + внутренний_радиус * cos(угол_дуги), 
                    центр_y + внутренний_радиус * sin(угол_дуги)
  кц
  поднять перо
  
  | Соединительные линии для эффекта переплетения
  угол := 2 * PI * i / количество_петель
  
  | Запоминаем координаты ключевых точек
  x1 := центр_x + внешний_радиус * cos(угол)
  y1 := центр_y + внешний_радиус * sin(угол)
  
  x2 := центр_x + внешний_радиус * cos(угол + PI / количество_петель)
  y2 := центр_y + внешний_радиус * sin(угол + PI / количество_петель)
  
  x3 := центр_x + внутренний_радиус * cos(угол + PI)
  y3 := центр_y + внутренний_радиус * sin(угол + PI)
  
  x4 := центр_x + внутренний_радиус * cos(угол + PI + PI / количество_петель)
  y4 := центр_y + внутренний_радиус * sin(угол + PI + PI / количество_петель)
  
  | Соединяем точки, имитируя переплетение
  если i mod 2 = 0 то
    | Одни линии проходят сверху
    сместиться в точку x1, y1
    опустить перо
    сместиться в точку x4, y4
    поднять перо
    
    сместиться в точку x2, y2
    опустить перо
    сместиться в точку x3, y3
    поднять перо
  иначе
    | Другие линии проходят снизу
    сместиться в точку x1, y1
    опустить перо
    сместиться в точку x3, y3
    поднять перо
    
    сместиться в точку x2, y2
    опустить перо
    сместиться в точку x4, y4
    поднять перо
  все
кц
кон
 
алг основной
нач
кельтское_переплетение(15, 15, 8, 6)
кон
Этот алгоритм создает переплетающиеся петли, характерные для кельтских орнаментов. Эффект переплетения достигается за счет продуманного порядка рисования линий и чередования "проходов сверху и снизу".

Задача 14: Геометрический паркет



Создадим паркетный узор из повторяющихся геометрических элементов:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
алг геометрический_паркет(x_начало, y_начало, размер_ячейки, строки, столбцы)
нач
цел i, j
 
нц для i от 0 до строки - 1
  нц для j от 0 до столбцы - 1
    | Выбираем тип узора в зависимости от четности координат
    если (i + j) mod 2 = 0 то
      | Рисуем узор типа 1 (квадрат с диагональю)
      сместиться в точку x_начало + j * размер_ячейки, y_начало + i * размер_ячейки
      опустить перо
      сместиться на вектор (размер_ячейки, 0)
      сместиться на вектор (0, размер_ячейки)
      сместиться на вектор (-размер_ячейки, 0)
      сместиться на вектор (0, -размер_ячейки)
      поднять перо
      
      | Добавляем диагональ
      сместиться в точку x_начало + j * размер_ячейки, y_начало + i * размер_ячейки
      опустить перо
      сместиться в точку x_начало + (j+1) * размер_ячейки, y_начало + (i+1) * размер_ячейки
      поднять перо
    иначе
      | Рисуем узор типа 2 (ромб)
      сместиться в точку x_начало + j * размер_ячейки + размер_ячейки/2, y_начало + i * размер_ячейки
      опустить перо
      сместиться в точку x_начало + (j+1) * размер_ячейки, y_начало + i * размер_ячейки + размер_ячейки/2
      сместиться в точку x_начало + j * размер_ячейки + размер_ячейки/2, y_начало + (i+1) * размер_ячейки
      сместиться в точку x_начало + j * размер_ячейки, y_начало + i * размер_ячейки + размер_ячейки/2
      сместиться в точку x_начало + j * размер_ячейки + размер_ячейки/2, y_начало + i * размер_ячейки
      поднять перо
    все
  кц
кц
кон
 
алг основной
нач
геометрический_паркет(2, 2, 4, 5, 6)
кон
Этот узор создает шахматноподобное чередование двух типов ячеек, формируя регулярный паркетный узор. Такой подход можно расширить на любое количество различных элементов и схем чередования.

Задача 15: Розетка (мандала)



Создадим круговой симметричный узор, напоминающий розетку или мандалу:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
алг розетка(центр_x, центр_y, внешний_радиус, количество_лепестков)
нач
цел i
вещ угол, шаг_угла, внутренний_радиус, средний_радиус
вещ контрольный_радиус
 
шаг_угла := 2 * PI / количество_лепестков
внутренний_радиус := внешний_радиус * 0.3
средний_радиус := внешний_радиус * 0.6
контрольный_радиус := внешний_радиус * 0.8
 
| Рисуем внешний круг
сместиться в точку центр_x + внешний_радиус, центр_y
опустить перо
нц для угол от 0 до 2*PI - PI/36 шаг PI/36
  сместиться в точку центр_x + внешний_радиус*cos(угол), центр_y + внешний_радиус*sin(угол)
кц
поднять перо
 
| Рисуем внутренний круг
сместиться в точку центр_x + внутренний_радиус, центр_y
опустить перо
нц для угол от 0 до 2*PI - PI/36 шаг PI/36
  сместиться в точку центр_x + внутренний_радиус*cos(угол), центр_y + внутренний_радиус*sin(угол)
кц
поднять перо
 
| Рисуем лепестки
нц для i от 0 до количество_лепестков - 1
  угол := i * шаг_угла
  
  | Рисуем изогнутый лепесток с использованием кривых Безье
  сместиться в точку центр_x + внутренний_радиус*cos(угол), центр_y + внутренний_радиус*sin(угол)
  опустить перо
  
  | Используем несколько промежуточных точек для приближения кривой
  нц для t от 0 до 1 шаг 0.05
    | Аппроксимация кривой Безье между внутренним и внешним радиусами
    сместиться в точку 
      центр_x + ((1-t)*внутренний_радиус + t*внешний_радиус) * cos(угол + t*шаг_угла*0.5),
      центр_y + ((1-t)*внутренний_радиус + t*внешний_радиус) * sin(угол + t*шаг_угла*0.5)
  кц
  
  | Завершаем лепесток, возвращаясь к внутреннему кругу
  нц для t от 1 до 0 шаг -0.05
    сместиться в точку 
      центр_x + ((1-t)*внутренний_радиус + t*внешний_радиус) * cos(угол + шаг_угла - t*шаг_угла*0.5),
      центр_y + ((1-t)*внутренний_радиус + t*внешний_радиус) * sin(угол + шаг_угла - t*шаг_угла*0.5)
  кц
  поднять перо
кц
кон
 
алг основной
нач
розетка(15, 15, 10, 8)
кон
Розеточные узоры широко используются в архитектуре и декоративном искусстве. В нашем алгоритме мы создаем сложную розетку с использованием аппроксимации кривых Безье для плавных лепестков. Орнаменты и узоры — это область, где алгоритмическое мышление и эстетическое чувство пересекаются самым прямым образом. Понимание математических закономерностей позволяет создавать сложные и красивые узоры с помощью относительно простого кода. Экспериментируйте с параметрами предложенных алгоритмов, комбинируйте различные техники и создавайте свои собственные уникальные орнаменты!

Рекурсивные узоры и фракталы



Фракталы и рекурсивные узоры представляют собой, пожалуй, самую захватывающую область работы с Чертёжником. Бесконечно повторяющиеся самоподобные структуры не только визуально привлекательны, но и служат отличной демонстрацией мощи рекурсивных алгоритмов.

Что такое фрактал? В простейшем понимании — это фигура, которая содержит свои уменьшенные копии внутри себя. Такая самоподобность может повторяться теоретически бесконечно, но в практических алгоритмах мы ограничиваем глубину рекурсии.

Рассмотрим несколько классических фрактальных структур и их реализацию в КуМире через Чертёжника.

Задача 16: Снежинка Коха



Одним из самых известных фракталов является снежинка Коха. Она начинается с равностороннего треугольника, а затем каждый отрезок заменяется на "горку" из четырёх отрезков длиной в три раза меньше исходного:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
алг линия_коха(x1, y1, x2, y2, уровень)
| Рисует фрактальную линию Коха заданного уровня
нач
вещ x3, y3, x4, y4, x5, y5
вещ длина, угол
 
| Базовый случай: на нулевом уровне просто рисуем линию
если уровень = 0 то
  сместиться в точку x1, y1
  опустить перо
  сместиться в точку x2, y2
  поднять перо
  выход
все
 
| Вычисляем длину отрезка и его угол наклона
длина := sqrt((x2-x1)^2 + (y2-y1)^2)
угол := arctan2(y2-y1, x2-x1)  | arctan2 - аналог функции atan2 в других языках
 
| Вычисляем координаты трёх новых точек
x3 := x1 + длина/3 * cos(угол)
y3 := y1 + длина/3 * sin(угол)
 
x4 := x3 + длина/3 * cos(угол - PI/3)
y4 := y3 + длина/3 * sin(угол - PI/3)
 
x5 := x1 + 2*длина/3 * cos(угол)
y5 := y1 + 2*длина/3 * sin(угол)
 
| Рекурсивно рисуем 4 отрезка уровня n-1
линия_коха(x1, y1, x3, y3, уровень-1)
линия_коха(x3, y3, x4, y4, уровень-1)
линия_коха(x4, y4, x5, y5, уровень-1)
линия_коха(x5, y5, x2, y2, уровень-1)
кон
 
алг снежинка_коха(центр_x, центр_y, размер, уровень)
| Рисует снежинку Коха - замкнутый фрактал из трёх линий Коха
нач
вещ угол, x1, y1, x2, y2, x3, y3
 
| Вычисляем координаты вершин исходного треугольника
x1 := центр_x
y1 := центр_y + размер
x2 := центр_x + размер * cos(PI/6)
y2 := центр_y - размер * sin(PI/6)
x3 := центр_x - размер * cos(PI/6)
y3 := центр_y - размер * sin(PI/6)
 
| Рисуем три стороны снежинки Коха
линия_коха(x1, y1, x2, y2, уровень)
линия_коха(x2, y2, x3, y3, уровень)
линия_коха(x3, y3, x1, y1, уровень)
кон
 
алг основной
нач
снежинка_коха(15, 15, 8, 4)  | Снежинка 4-го уровня
кон
Результат этого алгоритма — красивая снежинка с геометрически правильными "лучами" и выемками. С каждым увеличением параметра уровень границы фигуры становятся всё более сложными и детализированными.

Задача 17: Кривая Дракона



Кривая дракона — ещё один известный фрактал, который получается путем многократного сгибания полоски бумаги пополам:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
алг кривая_дракона(x1, y1, x2, y2, уровень, поворот)
| поворот: 1 - вправо, -1 - влево
нач
вещ x_средняя, y_средняя, угол, длина
 
| Базовый случай
если уровень = 0 то
  сместиться в точку x1, y1
  опустить перо
  сместиться в точку x2, y2
  поднять перо
  выход
все
 
| Находим среднюю точку
x_средняя := (x1 + x2) / 2
y_средняя := (y1 + y2) / 2
 
| Вычисляем угол наклона линии
угол := arctan2(y2 - y1, x2 - x1)
 
| Вычисляем длину отрезка
длина := sqrt((x2-x1)^2 + (y2-y1)^2) / sqrt(2)
 
| Находим новую точку поворота
x_поворот := x_средняя + длина * cos(угол + поворот * PI/4)
y_поворот := y_средняя + длина * sin(угол + поворот * PI/4)
 
| Рекурсивно рисуем две части кривой
кривая_дракона(x1, y1, x_поворот, y_поворот, уровень-1, 1)
кривая_дракона(x2, y2, x_поворот, y_поворот, уровень-1, -1)
кон
 
алг основной
нач
кривая_дракона(5, 10, 25, 10, 10, 1)  | Кривая 10-го уровня
кон
Этот алгоритм создаёт сложную извилистую кривую, которая напоминает силуэт дракона. Каждый уровень рекурсии добавляет новые изгибы, делая фрактал всё более сложным.

Задача 18: Треугольник Серпинского



Треугольник Серпинского — классический пример самоподобного фрактала, построенного на основе равностороннего треугольника:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
алг треугольник_серпинского(x1, y1, x2, y2, x3, y3, уровень)
нач
вещ x12, y12, x23, y23, x31, y31
 
| Базовый случай: рисуем просто треугольник
если уровень = 0 то
  сместиться в точку x1, y1
  опустить перо
  сместиться в точку x2, y2
  сместиться в точку x3, y3
  сместиться в точку x1, y1
  поднять перо
  выход
все
 
| Находим середины сторон
x12 := (x1 + x2) / 2
y12 := (y1 + y2) / 2
x23 := (x2 + x3) / 2
y23 := (y2 + y3) / 2
x31 := (x3 + x1) / 2
y31 := (y3 + y1) / 2
 
| Рекурсивно рисуем три меньших треугольника
треугольник_серпинского(x1, y1, x12, y12, x31, y31, уровень-1)
треугольник_серпинского(x12, y12, x2, y2, x23, y23, уровень-1)
треугольник_серпинского(x31, y31, x23, y23, x3, y3, уровень-1)
кон
 
алг основной
нач
| Задаём вершины начального треугольника
вещ x1, y1, x2, y2, x3, y3
 
x1 := 10
y1 := 5
x2 := 20
y2 := 5
x3 := 15
y3 := 5 + 5*sqrt(3)
 
треугольник_серпинского(x1, y1, x2, y2, x3, y3, 5)  | 5 уровней рекурсии
кон
Обратите внимание на ключевую особенность алгоритма: мы не рисуем центральный треугольник, а только три угловых треугольника. Это создаёт характерный узор с "дырками" в центре каждого уровня.

Задача 19: Фрактальное дерево



Фрактальные деревья — интуитивно понятный и красивый пример рекурсии в природе:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
алг фрактальное_дерево(x, y, длина, угол, уровень)
нач
вещ новый_x, новый_y
 
если уровень <= 0 то выход все
 
| Вычисляем конечную точку текущей ветви
новый_x := x + длина * cos(угол * PI / 180)
новый_y := y + длина * sin(угол * PI / 180)
 
| Рисуем текущую ветвь
сместиться в точку x, y
опустить перо
сместиться в точку новый_x, новый_y
поднять перо
 
| Рекурсивно рисуем левую и правую ветви
фрактальное_дерево(новый_x, новый_y, длина * 0.7, угол - 45, уровень - 1)
фрактальное_дерево(новый_x, новый_y, длина * 0.7, угол + 45, уровень - 1)
кон
 
алг основной
нач
фрактальное_дерево(15, 5, 7, 90, 7)  | Дерево 7-го уровня, растущее вверх
кон
Интересный эффект достигается, если модифицировать алгоритм, добавив случайные вариации длины и углов ветвей:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
алг натуралистичное_дерево(x, y, длина, угол, уровень)
нач
вещ новый_x, новый_y, случайная_длина, случайный_угол_1, случайный_угол_2
 
если уровень <= 0 то выход все
 
| Добавляем случайность в длину ветви (±20%)
случайная_длина := длина * (0.8 + random() * 0.4)
 
| Вычисляем конечную точку текущей ветви
новый_x := x + случайная_длина * cos(угол * PI / 180)
новый_y := y + случайная_длина * sin(угол * PI / 180)
 
| Рисуем текущую ветвь
сместиться в точку x, y
опустить перо
сместиться в точку новый_x, новый_y
поднять перо
 
| Случайные отклонения для углов ветвления (±15°)
случайный_угол_1 := 30 + random() * 30
случайный_угол_2 := 30 + random() * 30
 
| Рекурсивно рисуем левую и правую ветви с небольшой асимметрией
натуралистичное_дерево(новый_x, новый_y, длина * 0.7, угол - случайный_угол_1, уровень - 1)
натуралистичное_дерево(новый_x, новый_y, длина * 0.7, угол + случайный_угол_2, уровень - 1)
кон
Такой подход создает более органичное, "живое" изображение, в котором прослеживается фрактальная структура, но отсутствует механическая правильность.

Задача 20: Салфетка Серпинского



Этот фрактал представляет собой двумерное обобщение канторова множества, где из квадрата вырезается центральная часть:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
алг салфетка_серпинского(x, y, размер, уровень)
нач
вещ новый_размер, dx, dy
 
| Базовый случай: на нулевом уровне просто рисуем квадрат
если уровень = 0 то
  сместиться в точку x, y
  опустить перо
  сместиться на вектор (размер, 0)
  сместиться на вектор (0, размер)
  сместиться на вектор (-размер, 0)
  сместиться на вектор (0, -размер)
  поднять перо
  выход
все
 
| Размер подквадратов
новый_размер := размер / 3
 
| Рекурсивно рисуем 8 подквадратов (пропускаем центральный)
нц для dy от 0 до 2
нц для dx от 0 до 2
  если не (dx = 1 и dy = 1) то  | Пропускаем центральный квадрат
    салфетка_серпинского(x + dx * новый_размер, y + dy * новый_размер, новый_размер, уровень - 1)
  все
кц
кц
кон
 
алг основной
нач
салфетка_серпинского(5, 5, 18, 3)  | Салфетка 3-го уровня
кон
Работа с фракталами в Чертёжнике — прекрасная демонстрация силы рекурсивного мышления. Из простых правил, применяемых повторно на каждом уровне, возникают сложные и красивые структуры. При разработке фрактальных алгоритмов стоит учитывать несколько важных моментов:
1. Всегда определяйте базовый случай, чтобы рекурсия имела точку останова.
2. Следите за глубиной рекурсии — слишком глубокая рекурсия может привести к переполнению стека.
3. Обдумайте оптимальный алгоритм отрисовки, чтобы избежать повторного рисования одних и тех же линий.
4. Для сложных фракталов используйте предварительное планирование точек.

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

Генерация абстрактных рисунков со случайными числами



Создание абстрактных рисунков с использованием случайных чисел — увлекательное направление в программировании Чертёжника. Применяя элемент случайности, мы можем генерировать уникальные изображения, которые никогда не повторяются. Такой подход открывает дверь в мир алгоритмического искусства, где красота рождается из математических формул и генераторов случайных чисел. В КуМире для генерации случайных чисел используется функция random(), которая возвращает псевдослучайное число в диапазоне от 0 до 1. С её помощью мы можем создавать разнообразные эффекты, от хаотичных точечных узоров до плавных абстрактных форм.

Случайные точки и брызги



Начнём с простейшего примера — генерации облака случайных точек:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
алг случайные_точки(x_центр, y_центр, радиус, количество)
нач
цел i
вещ угол, расстояние, x, y
 
нц для i от 1 до количество
| Генерируем случайный угол от 0 до 2π
угол := random() * 2 * PI
  
| Генерируем случайное расстояние от центра (с большей вероятностью ближе к центру)
расстояние := радиус * sqrt(random())
  
| Вычисляем координаты точки
x := x_центр + расстояние * cos(угол)
y := y_центр + расстояние * sin(угол)
  
| Рисуем точку (маленький крестик)
сместиться в точку x, y
опустить перо
сместиться на вектор (0.1, 0.1)
сместиться на вектор (-0.2, -0.2)
поднять перо
сместиться в точку x, y
опустить перо
сместиться на вектор (0.1, -0.1)
сместиться на вектор (-0.2, 0.2)
поднять перо
кц
кон
Интересно, что используя sqrt(random()) вместо просто random() для расстояния, мы получаем более равномерное распределение точек по площади круга. Это иллюстрирует, как небольшое изменение в алгоритме может существенно повлиять на визуальный результат.

Стохастические линии



Создадим теперь эффект "случайного пути" — извилистой линии, каждый сегмент которой имеет случайное направление:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
алг случайный_путь(x_начало, y_начало, длина_шага, шагов, максимальный_поворот)
нач
цел i
вещ x, y, угол, поворот
 
x := x_начало
y := y_начало
угол := 0  | Начальное направление - вправо
 
сместиться в точку x, y
опустить перо
 
нц для i от 1 до шагов
| Генерируем случайное изменение угла в пределах максимального поворота
поворот := (random() * 2 - 1) * максимальный_поворот
  
| Обновляем угол движения
угол := угол + поворот
  
| Вычисляем новую позицию
x := x + длина_шага * cos(угол)
y := y + длина_шага * sin(угол)
  
| Перемещаемся в новую точку
сместиться в точку x, y
кц
 
поднять перо
кон
Этот алгоритм создаёт линию, напоминающую траекторию броуновского движения. Регулируя параметр максимальный_поворот, мы можем получать как плавные волнистые линии (при малых значениях), так и хаотичные зигзаги (при значениях близких к π).

Случайный ландшафт



Создадим алгоритм для генерации абстрактного "горного пейзажа" на основе случайных вариаций:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
алг случайный_ландшафт(x_мин, x_макс, y_среднее, шаг, амплитуда, сглаживание)
нач
вещ x, y, y_пред
цел i, шагов
вещ случайные_значения[]
 
шагов := (x_макс - x_мин) / шаг
 
| Предварительно генерируем случайные значения
нц для i от 0 до шагов
случайные_значения[i] := random() * 2 - 1
кц
 
| Сглаживаем значения для получения более плавного рельефа
нц для j от 1 до сглаживание
нц для i от 1 до шагов-1
случайные_значения[i] := (случайные_значения[i-1] + 
                           случайные_значения[i] * 2 + 
                           случайные_значения[i+1]) / 4
кц
кц
 
| Рисуем линию ландшафта
x := x_мин
y := y_среднее + амплитуда * случайные_значения[0]
сместиться в точку x, y
опустить перо
 
нц для i от 1 до шагов
x := x_мин + i * шаг
y := y_среднее + амплитуда * случайные_значения[i]
сместиться в точку x, y
кц
 
поднять перо
кон
В этом примере мы используем многоступенчатое сглаживание для получения более естественной линии. Чем больше значение параметра сглаживание, тем плавнее будет контур "гор".

Случайные узоры с симметрией



Интересный эффект можно получить, добавляя элемент случайности в симметричные узоры:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
алг симметричный_случайный_узор(центр_x, центр_y, размер, лучей, точек_на_луче)
нач
цел i, j
вещ угол_луча, расстояние, случайное_отклонение, угол
вещ x, y
 
нц для i от 0 до лучей-1
| Угол текущего луча
угол_луча := 2 * PI * i / лучей
  
нц для j от 1 до точек_на_луче
| Базовое расстояние от центра
расстояние := размер * j / точек_на_луче
    
| Случайное отклонение (±20% от шага между точками)
случайное_отклонение := (random() * 2 - 1) * 0.2 * размер / точек_на_луче
расстояние := расстояние + случайное_отклонение
    
| Добавляем случайное угловое отклонение
угол := угол_луча + (random() * 2 - 1) * 0.1
    
| Вычисляем координаты и рисуем точку
x := центр_x + расстояние * cos(угол)
y := центр_y + расстояние * sin(угол)
    
сместиться в точку x, y
опустить перо
| Рисуем точку как маленький круг
нц для а от 0 до 2*PI шаг PI/4
сместиться на вектор (0.1*cos(а), 0.1*sin(а))
кц
поднять перо
кц
кц
кон
Этот алгоритм создает узор из случайно расположенных точек, но с сохранением общей радиальной симметрии. Такой подход часто используется в алгоритмическом искусстве для создания абстрактных композиций, напоминающих природные формы.

Генератор абстрактных "клякс"



Создадим алгоритм для генерации плавных абстрактных форм, напоминающих кляксы или облака:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
алг абстрактная_клякса(центр_x, центр_y, базовый_радиус, искажения)
нач
цел i
вещ угол, радиус, амплитуды[10], фазы[10], x, y
 
| Инициализируем случайные амплитуды и фазы для гармоник
нц для i от 1 до искажения
амплитуды[i] := random() * 0.3
фазы[i] := random() * 2 * PI
кц
 
| Рисуем замкнутый контур
сместиться в точку центр_x + базовый_радиус, центр_y
опустить перо
 
нц для угол от 0 до 2*PI шаг PI/36
| Рассчитываем радиус с учётом гармоник
радиус := базовый_радиус
 
нц для i от 1 до искажения
| Добавляем гармоники разных частот
радиус := радиус + базовый_радиус * амплитуды[i] * sin(i * угол + фазы[i])
кц
  
x := центр_x + радиус * cos(угол)
y := центр_y + радиус * sin(угол)
сместиться в точку x, y
кц
 
| Замыкаем контур
сместиться в точку центр_x + базовый_радиус, центр_y
поднять перо
кон
Этот алгоритм использует сумму синусоид с различными частотами, амплитудами и фазовыми сдвигами, что даёт плавные деформации круга. Такой метод известен как гармонический анализ формы и часто используется в компьютерной графике.

Случайные текстуры



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

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
алг случайная_текстура(x_начало, y_начало, ширина, высота, размер_ячейки, плотность)
нач
цел i, j
вещ x, y
 
нц для i от 0 до floor(ширина / размер_ячейки) - 1
нц для j от 0 до floor(высота / размер_ячейки) - 1
| С вероятностью "плотность" рисуем ячейку
если random() < плотность то
x := x_начало + i * размер_ячейки
y := y_начало + j * размер_ячейки
      
| Выбираем случайно один из трёх типов заполнения ячейки
выбор := floor(random() * 3)
      
если выбор = 0 то
| Закрашиваем горизонтальными линиями
нц для dy от 0 до размер_ячейки шаг размер_ячейки/5
сместиться в точку x, y + dy
опустить перо
сместиться в точку x + размер_ячейки, y + dy
поднять перо
кц
иначе если выбор = 1 то
| Закрашиваем вертикальными линиями
нц для dx от 0 до размер_ячейки шаг размер_ячейки/5
сместиться в точку x + dx, y
опустить перо
сместиться в точку x + dx, y + размер_ячейки
поднять перо
кц
иначе
| Закрашиваем диагональными линиями
нц для t от 0 до 1 шаг 0.2
сместиться в точку x + t*размер_ячейки, y
опустить перо
сместиться в точку x + размер_ячейки, y + t*размер_ячейки
поднять перо
          
сместиться в точку x, y + t*размер_ячейки
опустить перо
сместиться в точку x + (1-t)*размер_ячейки, y + размер_ячейки
поднять перо
кц
все
все
кц
кц
кон
Этот алгоритм создаёт сетку ячеек, каждая из которых с определённой вероятностью заполняется одним из трёх типов штриховки. Результат напоминает абстрактные композиции в стиле конструктивизма.

Используя случайные числа в алгоритмах Чертёжника, мы можем создавать бесконечное разнообразие уникальных изображений. Главное преимущество такого подхода — возможность получать сложные и интересные результаты с помощью относительно простого кода. Экспериментируйте с параметрами, комбинируйте разные техники и создавайте свои собственные алгоритмы генеративного искусства!

Разработка и решение комплексных задач



Теперь, когда мы освоили различные техники работы с Чертёжником, пришло время объединить полученные знания для решения по-настоящему комплексных задач. В этом разделе мы рассмотрим примеры сложных проектов, требующих комбинации различных приёмов и алгоритмов.

Задача 21: Часы с движущимися стрелками



Создадим аналоговые часы с тремя стрелками, которые можно анимировать, показывая текущее или заданное время:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
алг часы(центр_x, центр_y, радиус, часы, минуты, секунды)
нач
вещ угол_часов, угол_минут, угол_секунд
вещ длина_часовой, длина_минутной, длина_секундной
 
| Вычисляем углы для стрелок
угол_часов := (часы mod 12 + минуты / 60) * 30 * PI / 180 - PI/2
угол_минут := (минуты + секунды / 60) * 6 * PI / 180 - PI/2
угол_секунд := секунды * 6 * PI / 180 - PI/2
 
| Задаём длины стрелок
длина_часовой := радиус * 0.5
длина_минутной := радиус * 0.7
длина_секундной := радиус * 0.9
 
| Рисуем циферблат
сместиться в точку центр_x + радиус, центр_y
опустить перо
нц для угол от 0 до 2*PI шаг PI/30
  сместиться в точку центр_x + радиус*cos(угол), центр_y + радиус*sin(угол)
кц
поднять перо
 
| Рисуем метки часов
нц для i от 1 до 12
  угол := i * 30 * PI / 180 - PI/2
  
  | Внешняя точка метки
  сместиться в точку центр_x + радиус*cos(угол), центр_y + радиус*sin(угол)
  опустить перо
  
  | Внутренняя точка метки
  сместиться в точку центр_x + радиус*0.9*cos(угол), центр_y + радиус*0.9*sin(угол)
  поднять перо
кц
 
| Рисуем часовую стрелку
сместиться в точку центр_x, центр_y
опустить перо
сместиться в точку центр_x + длина_часовой*cos(угол_часов), 
            центр_y + длина_часовой*sin(угол_часов)
поднять перо
 
| Рисуем минутную стрелку
сместиться в точку центр_x, центр_y
опустить перо
сместиться в точку центр_x + длина_минутной*cos(угол_минут), 
            центр_y + длина_минутной*sin(угол_минут)
поднять перо
 
| Рисуем секундную стрелку
сместиться в точку центр_x, центр_y
опустить перо
сместиться в точку центр_x + длина_секундной*cos(угол_секунд), 
            центр_y + длина_секундной*sin(угол_секунд)
поднять перо
кон
Этот алгоритм создаёт красивую модель аналоговых часов. Для создания анимации движущихся стрелок нужно последовательно перерисовывать часы с обновляемыми значениями времени, хотя в стандартном КуМире это требует дополнительных приёмов для очистки экрана.

Задача 22: Планетарная система



Смоделируем упрощённую планетарную систему с несколькими планетами, вращающимися вокруг звезды:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
алг планетарная_система(центр_x, центр_y, количество_планет, шагов_времени)
нач
цел i, j
вещ радиусы[10], скорости[10], фазы[10], размеры[10], угол
 
| Инициализируем параметры планет
нц для i от 1 до количество_планет
  | Расстояние от звезды
  радиусы[i] := 3 + i * 2
  
  | Скорость вращения (обратно пропорциональна расстоянию)
  скорости[i] := 0.1 / sqrt(радиусы[i])
  
  | Начальная фаза
  фазы[i] := random() * 2 * PI
  
  | Размер планеты
  размеры[i] := 0.3 + random() * 0.5
кц
 
| Рисуем звезду
сместиться в точку центр_x, центр_y
опустить перо
нц для угол от 0 до 2*PI шаг PI/18
  сместиться в точку центр_x + cos(угол), центр_y + sin(угол)
кц
поднять перо
 
| Моделируем движение планет
нц для j от 1 до шагов_времени
  | Очищаем предыдущее положение планет (в реальном КуМире нужны специальные функции)
  
  | Рисуем новое положение планет
  нц для i от 1 до количество_планет
    угол := фазы[i] + j * скорости[i]
    
    | Рисуем орбиту
    если j = 1 то
      сместиться в точку центр_x + радиусы[i], центр_y
      опустить перо
      нц для а от 0 до 2*PI шаг PI/36
        сместиться в точку центр_x + радиусы[i]*cos(а), центр_y + радиусы[i]*sin(а)
      кц
      поднять перо
    все
    
    | Рисуем планету
    сместиться в точку центр_x + радиусы[i]*cos(угол), центр_y + радиусы[i]*sin(угол)
    опустить перо
    нц для а от 0 до 2*PI шаг PI/8
      сместиться на вектор (размеры[i]*cos(а), размеры[i]*sin(а))
    кц
    поднять перо
  кц
  
  | Задержка для анимации (в реальном КуМире нужны специальные функции)
кц
кон
Этот алгоритм моделирует планеты, вращающиеся вокруг центральной звезды с разными скоростями. Для создания реалистичной анимации требуется очистка экрана между кадрами, что в базовом КуМире может быть реализовано с использованием специальных возможностей среды.

Задача 23: Генератор лабиринтов



Создадим алгоритм для генерации простых лабиринтов методом "прорубания стен":

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
алг лабиринт(x_начало, y_начало, ширина, высота, размер_ячейки)
нач
цел сетка[50][50] | Представление лабиринта: 1 - стена, 0 - проход
цел i, j, x, y, новый_x, новый_y, направление
цел dx[4], dy[4], посещено, всего_ячеек
цел стек_x[1000], стек_y[1000], стек_размер
 
| Направления перемещения: право, вниз, лево, вверх
dx[0] := 2
dx[1] := 0
dx[2] := -2
dx[3] := 0
 
dy[0] := 0
dy[1] := 2
dy[2] := 0
dy[3] := -2
 
| Инициализация сетки (все ячейки - стены)
нц для i от 0 до ширина-1
  нц для j от 0 до высота-1
    сетка[i][j] := 1
  кц
кц
 
| Начальная позиция
x := 1
y := 1
сетка[x][y] := 0
стек_x[0] := x
стек_y[0] := y
стек_размер := 1
посещено := 1
всего_ячеек := (ширина div 2) * (высота div 2)
 
| Генерируем лабиринт методом обхода в глубину
нц пока посещено < всего_ячеек и стек_размер > 0
  | Получаем текущую позицию из стека
  x := стек_x[стек_размер-1]
  y := стек_y[стек_размер-1]
  
  | Проверяем возможные направления движения
  цел возможные_направления[4], количество_направлений, случайный_индекс
  количество_направлений := 0
  
  нц для i от 0 до 3
    новый_x := x + dx[i]
    новый_y := y + dy[i]
    
    | Проверяем, находится ли новая ячейка в пределах лабиринта и не посещена ли она
    если новый_x >= 1 и новый_x < ширина-1 и новый_y >= 1 и новый_y < высота-1 и сетка[новый_x][новый_y] = 1 то
      возможные_направления[количество_направлений] := i
      количество_направлений := количество_направлений + 1
    все
  кц
  
  если количество_направлений > 0 то
    | Случайно выбираем направление
    случайный_индекс := floor(random() * количество_направлений)
    направление := возможные_направления[случайный_индекс]
    
    | Вычисляем новую позицию и позицию стены между ячейками
    новый_x := x + dx[направление]
    новый_y := y + dy[направление]
    сетка[x + dx[направление]/2][y + dy[направление]/2] := 0 | Убираем стену
    сетка[новый_x][новый_y] := 0 | Отмечаем новую ячейку как посещенную
    
    | Добавляем новую позицию в стек
    стек_x[стек_размер] := новый_x
    стек_y[стек_размер] := новый_y
    стек_размер := стек_размер + 1
    посещено := посещено + 1
  иначе
    | Возвращаемся назад
    стек_размер := стек_размер - 1
  все
кц
 
| Рисуем лабиринт
нц для i от 0 до ширина-1
  нц для j от 0 до высота-1
    если сетка[i][j] = 1 то
      | Рисуем стену
      сместиться в точку x_начало + i * размер_ячейки, y_начало + j * размер_ячейки
      опустить перо
      сместиться на вектор (размер_ячейки, 0)
      сместиться на вектор (0, размер_ячейки)
      сместиться на вектор (-размер_ячейки, 0)
      сместиться на вектор (0, -размер_ячейки)
      поднять перо
    все
  кц
кц
кон
Этот алгоритм генерирует случайный лабиринт методом обхода в глубину с "прорубанием стен". Для упрощения мы используем фиксированные массивы, но в реальном проекте стоит использовать динамические структуры данных.

Задача 24: Интерактивная игра "Змейка"



Создадим базовую версию известной игры "Змейка" с использованием Чертёжника:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
алг змейка(ширина_поля, высота_поля, размер_ячейки)
нач
цел змейка_x[500], змейка_y[500], длина_змейки
цел еда_x, еда_y, направление, следующее_направление
цел i, j
 
| Инициализация змейки
длина_змейки := 3
нц для i от 0 до длина_змейки - 1
  змейка_x[i] := ширина_поля / 2 - i
  змейка_y[i] := высота_поля / 2
кц
 
| Начальное направление (0 - вправо, 1 - вниз, 2 - влево, 3 - вверх)
направление := 0
следующее_направление := направление
 
| Размещаем первую еду
еда_x := floor(random() * ширина_поля)
еда_y := floor(random() * высота_поля)
 
| Игровой цикл
цел игра_окончена := 0
 
нц пока не игра_окончена
  | Очищаем экран (в реальном КуМире нужны специальные функции)
  
  | Рисуем границы поля
  сместиться в точку 0, 0
  опустить перо
  сместиться в точку ширина_поля * размер_ячейки, 0
  сместиться в точку ширина_поля * размер_ячейки, высота_поля * размер_ячейки
  сместиться в точку 0, высота_поля * размер_ячейки
  сместиться в точку 0, 0
  поднять перо
  
  | Обрабатываем ввод пользователя (в реальном КуМире нужны специальные функции)
  | Например, получаем направление из клавиатуры
  | направление := получить_направление()
  
  | Обновляем направление, не позволяя двигаться в противоположную сторону
  если (следующее_направление + 2) mod 4 <> направление то
    направление := следующее_направление
  все
  
  | Перемещаем змейку
  нц для i от длина_змейки - 1 до 1 шаг -1
    змейка_x[i] := змейка_x[i-1]
    змейка_y[i] := змейка_y[i-1]
  кц
  
  | Обновляем голову змейки согласно направлению
  если направление = 0 то змейка_x[0] := змейка_x[0] + 1
  иначе если направление = 1 то змейка_y[0] := змейка_y[0] + 1
  иначе если направление = 2 то змейка_x[0] := змейка_x[0] - 1
  иначе змейка_y[0] := змейка_y[0] - 1
  все
  
  | Проверяем столкновение со стеной
  если змейка_x[0] < 0 или змейка_x[0] >= ширина_поля
   или змейка_y[0] < 0 или змейка_y[0] >= высота_поля то
    игра_окончена := 1
  все
  
  | Проверяем столкновение с собственным телом
  нц для i от 1 до длина_змейки - 1
    если змейка_x[0] = змейка_x[i] и змейка_y[0] = змейка_y[i] то
      игра_окончена := 1
    все
  кц
  
  | Проверяем, съела ли змейка еду
  если змейка_x[0] = еда_x и змейка_y[0] = еда_y то
    | Увеличиваем длину змейки
    длина_змейки := длина_змейки + 1
    
    | Размещаем новую еду
    цел валидная_позиция := 0
    нц пока не валидная_позиция
      еда_x := floor(random() * ширина_поля)
      еда_y := floor(random() * высота_поля)
      
      валидная_позиция := 1
      нц для i от 0 до длина_змейки - 1
        если змейка_x[i] = еда_x и змейка_y[i] = еда_y то
          валидная_позиция := 0
        все
      кц
    кц
  все
  
  | Рисуем змейку
  нц для i от 0 до длина_змейки - 1
    сместиться в точку змейка_x[i] * размер_ячейки, змейка_y[i] * размер_ячейки
    опустить перо
    сместиться на вектор (размер_ячейки, 0)
    сместиться на вектор (0, размер_ячейки)
    сместиться на вектор (-размер_ячейки, 0)
    сместиться на вектор (0, -размер_ячейки)
    поднять перо
  кц
  
  | Рисуем еду
  сместиться в точку еда_x * размер_ячейки + размер_ячейки/2, еда_y * размер_ячейки + размер_ячейки/2
  опустить перо
  нц для угол от 0 до 2*PI шаг PI/8
    сместиться на вектор (размер_ячейки/3 * cos(угол), размер_ячейки/3 * sin(угол))
  кц
  поднять перо
  
  | Задержка для управления скоростью игры
кц
 
| Выводим сообщение о конце игры
| (в реальном КуМире используются специальные функции)
кон
Эта реализация демонстрирует структуру интерактивной игры. В реальной среде КуМир потребуются дополнительные функции для обработки ввода пользователя, очистки экрана и контроля времени.

Задача 25: Художественная композиция "Городской пейзаж"



Создадим художественную композицию, изображающую городской пейзаж с небоскребами различной высоты на фоне звездного неба:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
алг городской_пейзаж(ширина, высота)
нач
цел i, j, количество_звезд, количество_зданий
вещ x, y, размер, небо_высота
 
| Параметры композиции
количество_звезд := 100
количество_зданий := 15
небо_высота := высота * 0.7
 
| Рисуем фон - небо
сместиться в точку 0, небо_высота
опустить перо
сместиться в точку 0, высота
сместиться в точку ширина, высота
сместиться в точку ширина, небо_высота
поднять перо
 
| Рисуем звёзды на небе
нц для i от 1 до количество_звезд
  x := random() * ширина
  y := небо_высота + random() * (высота - небо_высота)
  размер := 0.05 + random() * 0.1
  
  | Рисуем звезду (крестик или точка)
  если random() < 0.2 то
    | Яркая звезда (крестик)
    сместиться в точку x - размер, y
    опустить перо
    сместиться в точку x + размер, y
    поднять перо
    сместиться в точку x, y - размер
    опустить перо
    сместиться в точку x, y + размер
    поднять перо
  иначе
    | Обычная звезда (точка)
    сместиться в точку x, y
    опустить перо
    сместиться на вектор (0.01, 0.01)
    поднять перо
  все
кц
 
| Рисуем луну
вещ луна_x, луна_y, луна_радиус
луна_x := ширина * 0.8
луна_y := высота * 0.9
луна_радиус := высота * 0.05
 
сместиться в точку луна_x, луна_y
опустить перо
нц для угол от 0 до 2*PI шаг PI/20
  сместиться в точку луна_x + луна_радиус * cos(угол), луна_y + луна_радиус * sin(угол)
кц
поднять перо
 
| Рисуем здания
вещ ширина_здания, высота_здания, x_здания, y_здания
вещ ширина_окна, высота_окна, окна_в_ряду, окон_в_колонке
 
нц для i от 0 до количество_зданий - 1
  ширина_здания := ширина / количество_зданий * (0.7 + random() * 0.5)
  высота_здания := небо_высота * (0.4 + random() * 0.6)
  x_здания := i * ширина / количество_зданий
  y_здания := 0
  
  | Рисуем контур здания
  сместиться в точку x_здания, y_здания
  опустить перо
  сместиться в точку x_здания, y_здания + высота_здания
  сместиться в точку x_здания + ширина_здания, y_здания + высота_здания
  сместиться в точку x_здания + ширина_здания, y_здания
  поднять перо
  
  | Рисуем окна
  окна_в_ряду := 2 + floor(random() * 4)
  окон_в_колонке := 4 + floor(random() * 8)
  ширина_окна := ширина_здания / (окна_в_ряду * 2)
  высота_окна := высота_здания / (окон_в_колонке * 2)
  
  нц для j_окно от 0 до окон_в_колонке - 1
    нц для i_окно от 0 до окна_в_ряду - 1
      | Рисуем окно только если случайное число меньше 0.7 (некоторые окна не горят)
      если random() < 0.7 то
        сместиться в точку x_здания + ширина_здания * (i_окно + 0.5) / окна_в_ряду, 
                      y_здания + высота_здания * (j_окно + 0.5) / окон_в_колонке
        опустить перо
        сместиться на вектор (ширина_окна, 0)
        сместиться на вектор (0, высота_окна)
        сместиться на вектор (-ширина_окна, 0)
        сместиться на вектор (0, -высота_окна)
        поднять перо
      все
    кц
  кц
кц
кон
Эта художественная композиция сочетает в себе несколько техник: рисование звёздного неба с луной и городского силуэта с зданиями, имеющими окна. Случайные вариации в размерах и расположении создают более реалистичный вид. Комплексные задачи демонстрируют, как сочетание разных алгоритмических приёмов позволяет создавать сложные и интересные изображения с помощью Чертёжника. Работая над такими проектами, вы развиваете не только навыки программирования, но и алгоритмическое мышление, умение декомпозировать задачи и творческий подход.

Методика создания собственных задач для Чертежника



Возможность создавать собственные задачи для Чертёжника — это уникальный шанс не только проверить свои навыки программирования, но и развить творческое мышление. Когда вы придумываете задачи сами, а не просто решаете готовые, вы начинаете глубже понимать принципы алгоритмического мышления и возможности исполнителя. Я годами наблюдал, как разница между просто хорошими и выдающимися программистами часто определяется именно умением формулировать задачи. Давайте разберём поэтапную методику создания интересных и обучающих задач для Чертёжника.

От идеи к формулировке



Первый шаг в создании собственных задач — поиск источника вдохновения. Им может стать буквально что угодно:
1. Реальные объекты вокруг вас. Посмотрите на предметы на столе, архитектурные элементы здания, природные формы — всё это можно упростить и представить как задачу для Чертёжника.
2. Математические концепции. Графики функций, геометрические преобразования, кривые из аналитической геометрии — богатый источник идей.
3. Художественные узоры и орнаменты. Национальные узоры, декоративные элементы — отличная основа для программых изображений.
4. Игры и головоломки. Классические игры вроде "крестиков-ноликов" или шахматной доски можно реализовать через Чертёжника.

Допустим, вы увидели интересный орнамент на обоях. Чаще всего орнаменты имеют регулярную структуру, в которой можно выделить повторяющиеся элементы. Именно эта повторяемость делает их хорошими кандидатами для алгоритмического представления.

Структурирование задачи



После выбора идеи нужно структурировать её в формат задачи:
1. Определите входные параметры. Какие характеристики своего рисунка вы хотите сделать изменяемыми? Размер, положение, количество элементов?
2. Создайте подзадачи. Разбейте сложный рисунок на логические части, которые можно реализовать отдельными вспомогательными алгоритмами.
3. Предусмотрите различные уровни сложности. Хорошая задача должна иметь базовый вариант решения и возможности для усложнения.

Например, для орнамента на обоях структура могла бы выглядеть так:
Входные параметры: размер узора, частота повторения, цветовая схема (если среда поддерживает)
Подзадачи: рисование базового элемента, создание линии из элементов, заполнение плоскости
Усложнения: добавление случайных вариаций, создание бордюров, комбинирование разных типов элементов

Формирование требований задачи



Когда у вас есть структура, сформулируйте четкие требования:

Code
1
2
3
4
Задача "Цветочный орнамент":
1. Создать алгоритм рисования цветка с параметрами: центр, размер лепестков, количество лепестков.
2. Создать алгоритм размещения цветов в виде орнамента: количество строк, количество столбцов.
3. Дополнительно: добавить случайные вариации размера цветов (±20%).
Важно, чтобы требования были конкретными, но оставляли простор для творческого подхода. Слишком жесткие ограничения могут сделать задачу механической, а слишком размытые — сбивающими с толку.

От простого к сложному



При создании комплекса задач полезно выстраивать их в порядке увеличения сложности. Я заметил, что самые эффективные задачники часто используют этот принцип:
1. Базовые навыки. Первые задачи должны тренировать основные команды перемещения и управления пером.
2. Основные алгоритмические конструкции. Следующий уровень — задачи на использование циклов и условий.
3. Модульность и вспомогательные алгоритмы. Затем переходим к задачам, требующим декомпозиции и создания подпрограмм.
4. Математические концепции. Далее идут задачи, требующие понимания математических принципов (функции, параметрические уравнения).
5. Комплексные проекты. Наконец, задачи, интегрирующие все предыдущие навыки в единый проект.

Проверка качества задачи



Прежде чем делиться своей задачей с другими, проверьте её качество:
1. Решите задачу сами. Это поможет выявить неточности в формулировке и оценить сложность.
2. Проанализируйте различные подходы. Существует ли несколько способов решения? Какой из них оптимальный?
3. Предусмотрите типичные ошибки. Какие трудности могут возникнуть у решающего? Как помочь их преодолеть?

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

Документирование и обмен идеями



Собственные задачи становятся ценнее, когда вы делитесь ими с сообществом:
1. Создайте библиотеку задач с четкой категоризацией по типам и уровням сложности.
2. Включите решения и комментарии к ним, объясняющие ключевые моменты.
3. Собирайте обратную связь от тех, кто решает ваши задачи, и улучшайте формулировки.

Когда я начал собирать свою коллекцию задач для Чертёжника, они были довольно примитивными. Но с каждой новой задачей, с каждым отзывом от студентов уровень и качество повышались. Сегодня некоторые из этих задач используются в курсах программирования.

Создание задач — это не только способ помочь другим учиться, но и прекрасная возможность для собственного развития. Придумывая интересные задачи для Чертёжника, вы тренируете алгоритмическое мышление, творческий подход к программированию и умение ясно выражать свои мысли — навыки, которые пригодятся в любой области разработки.

Стратегия обучения и интеграция с другими исполнителями



Освоение Чертёжника, как и любого другого инструмента программирования, требует определённой стратегии. Многолетний опыт преподавания показывает, что последовательный подход "от простого к сложному" даёт наилучшие результаты. Рассмотрим эффективную стратегию для изучения Чертёжника и как можно объединять его возможности с другими исполнителями в КуМире.

Первый этап обучения должен быть посвящен освоению базовых команд: перемещение, поднятие и опускание пера. Эти навыки закладывают фундамент для всей дальнейшей работы. Начните с рисования простых фигур — линий, квадратов, треугольников. Это помогает развить пространственное мышление и понимание координатной системы.

Важно сразу формировать правильное алгоритмическое мышление — умение разбивать сложную задачу на простые шаги. При рисовании даже простого прямоугольника нужно мыслить последовательностью: перейти в начальную точку, опустить перо, нарисовать стороны, поднять перо. Такой подход пригодится при решении любых задач программирования в будущем.

Второй этап может включать использование переменных и параметризацию алгоритмов. Когда ученик научился рисовать квадрат с фиксированными размерами, пришло время научить его создавать квадрат произвольного размера, вводимого пользователем. Это важный переходный момент от конкретного мышления к абстрактному. Я помню, как один ученик долго не мог понять, зачем нам переменные, если можно просто указать конкретные координаты. Но когда мы попробовали нарисовать 10 квадратов разного размера, он сразу оценил мощь параметризованного кода.

Третий этап — введение циклов и условных конструкций. Здесь удобно начать с задач на повторяющиеся структуры: нарисовать несколько одинаковых фигур в ряд, создать сетку из элементов, реализовать простые орнаменты. Циклы демонстрируют один из главных принципов программирования — автоматизацию повторяющихся действий. Хороший прием при обучении циклам — сначала написать линейный алгоритм, а потом показать, как его можно оптимизировать с помощью цикла. Это наглядно показывает преимущество алгоритмического мышления.

Четвертый этап — модульное программирование через вспомогательные алгоритмы. Ученик должен научиться выделять повторяющиеся блоки кода в отдельные процедуры. Это отличная подготовка к объектно-ориентированному программированию в будущем.

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

Пятый этап — изучение рекурсивных алгоритмов и фрактальной графики. Здесь ученики сталкиваются с новым уровнем абстракции, когда функция вызывает сама себя. Фракталы — идеальные объекты для демонстрации мощи рекурсии и развития алгоритмического воображения.

Шестой этап — интеграция с другими исполнителями КуМира. Система КуМир предоставляет несколько исполнителей, каждый со своими возможностями, и их комбинирование открывает новые перспективы. Особенно плодотворным может быть взаимодействие Чертёжника с Роботом. Робот действует в дискретном клеточном поле и может перемещаться, обнаруживать стены, закрашивать клетки. Комбинируя их, можно создавать интересные проекты:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
алг РоботРисуетПоКартеЧертежником(масштаб)
| Алгоритм, где Робот исследует лабиринт, а Чертежник его зарисовывает
нач
цел x, y | текущие координаты Робота
вещ смещение_x, смещение_y | начальное смещение для рисунка
  
| Запоминаем начальную позицию Робота
x := Поз_X()
y := Поз_Y()
смещение_x := 5 | Смещение рисунка от начала координат
смещение_y := 5
  
| Подготавливаем Чертежника
Чертежник
нс в точку смещение_x+x*масштаб, смещение_y+y*масштаб
опустить перо
кч
  
| Исследуем лабиринт и одновременно рисуем его
нц пока не справа свободно | Пример простого алгоритма прохождения
  если сверху свободно то
    | Идем наверх
    вверх
    
    | Рисуем перемещение
    Чертежник
    нс в точку смещение_x+Поз_X()*масштаб, смещение_y+Поз_Y()*масштаб
    кч
  иначе
    если снизу свободно то
      | Идем вниз
      вниз
      
      | Рисуем перемещение
      Чертежник
      нс в точку смещение_x+Поз_X()*масштаб, смещение_y+Поз_Y()*масштаб
      кч
    иначе
      | Идем влево
      влево
      
      | Рисуем перемещение
      Чертежник
      нс в точку смещение_x+Поз_X()*масштаб, смещение_y+Поз_Y()*масштаб
      кч
    все
  все
кц
  
| Завершаем рисование
Чертежник
поднять перо
кч
кон
Ещё один интересный пример — интеграция Чертёжника с исполнителем Рисователь, который имеет более продвинутые графические возможности:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
алг ЧертежникДляРисователя
нач
| Чертежник создает контуры
Чертежник
нс в точку 10, 10
опустить перо
нс в точку 20, 10
нс в точку 20, 20
нс в точку 10, 20
нс в точку 10, 10
поднять перо
кч
 
| Рисователь закрашивает фигуру
Рисователь
нов изображение(30, 30)
кисть(красный)
залить(15, 15)
кч
кон
Такие интегрированные проекты не только закрепляют навыки работы с каждым исполнителем, но и развивают системное мышление — умение видеть, как разные компоненты могут взаимодействовать для решения более сложных задач.

Для успешного обучения также важно правильно выбирать задачи. Они должны быть:
1. Постепенно возрастающей сложности.
2. Интересными и мотивирующими.
3. Связанными с реальным миром или другими областями знаний.
4. Доступными, но требующими некоторого интеллектуального усилия.

Один из эффективных подходов — проектное обучение. Вместо множества разрозненных задач предложите ученикам разработать единый проект, постепенно наращивая его функциональность. Например, начать с создания простой карты местности, потом добавить масштабирование, затем интерактивность с помощью Робота, и в конце — визуальные эффекты через Рисователя.

Исполнитель КУЗНЕЧИК живёт на числовой оси
Исполнитель КУЗНЕЧИК живёт на числовой оси. Начальное положение КУЗНЕЧИКА – точка 0. Система команд Кузнечика: Вперед 7 – Кузнечик прыгает вперёд...

Исполнитель Черепаха
Честно говоря, без понятия куда обратиться из разделов. Не помогли бы разобраться с кодом на кумире(без понятия что за исполнитель...) ...

Исполнитель Черепаха
У меня проблема с использованием исполнителя черепахи в кумире: когда я запускаю код, на карте, на которой расположена черепаха, почему-то нет...

[Чертежник] Построение графика функции y = 10cos(x) - 5 на отрезке [a, b] с использованием алгоритма-функции
Исполнитель Чертежник. Составьте вспомогательный алгоритм-функцию для построения графика функции y = 10cos(x) - 5 на отрезке . Значения a и b...

[Чертежник] Построение графика y = 3x^2 - 6 на отрезке [a, b] с использованием алгоритма-функции
Исполнитель Чертежник. Составьте вспомогательный алгоритм-функцию для построения графика y = 3x2 - 6 на отрезке . Значения a и b задаются...

[Чертежник] Построение графика y = 20 - 15sin(x) на отрезке [a, b] с использованием алгоритма-функции
Исполнитель Чертежник. Составьте вспомогательный алгоритм-функцию для построения графика y = 20 - 15sin(x) на отрезке . Значения a и b задаются...

[Чертежник] Построение графика y = (x - 5)^2 на отрезке [a, b] с использованием алгоритма-функции
Исполнитель Чертежник. Составьте вспомогательный алгоритм-функцию для построения графика y = (x - 5)2 на отрезке . Значения a и b задаются...

[Чертежник] Построение графика y = 5x^3 на отрезке [a, b] с использованием алгоритма-функции
Исполнитель Чертежник. Составьте вспомогательный алгоритм-функцию для построения графика y = 5x3 на отрезке . Значения a и b задаются пользователем....

[Чертежник] Построение графика y = 10e^x на отрезке [a, b] с использованием алгоритма-функции
Исполнитель Чертежник. Составьте вспомогательный алгоритм-функцию для построения графика y = 10ex на отрезке . Значения a и b задаются пользователем....

[Чертежник] Построение графика y = x - 4sin(x) на отрезке [a, b] с использованием алгоритма-функции
Исполнитель Чертежник. Составьте вспомогательный алгоритм-функцию для построения графика y = x - 4sin(x) на отрезке . Значения a и b задаются...

[Чертежник] Построение графика y = x^2 x - 5 на отрезке [a, b] с использованием алгоритма-функции
Исполнитель Чертежник. Составьте вспомогательный алгоритм-функцию для построения графика y = x2 + x - 5 на отрезке . Значения a и b задаются...

Исполнитель Чертежник Составьте вспомогательный алгоритм-функцию Построение графика y = 50e-xsin(x) на отрезке [a, b]
Исполнитель Чертежник. Составьте вспомогательный алгоритм-функцию для построения графика y = 50e-xsin(x) на отрезке . Значения a и b задаются...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 0
Комментарии
 
Новые блоги и статьи
Согласованность транзакций в MongoDB
Codd 30.04.2025
MongoDB, начинавшая свой путь как классическая NoSQL система с акцентом на гибкость и масштабируемость, сильно спрогрессировала, включив в свой арсенал поддержку транзакционной согласованности. Это. . .
Продвинутый ввод-вывод в Java: NIO, NIO.2 и асинхронный I/O
Javaican 30.04.2025
Когда речь заходит о вводе-выводе в Java, классический пакет java. io долгие годы был единственным вариантом для разработчиков, но его ограничения становились всё очевиднее с ростом требований к. . .
Обнаружение объектов в реальном времени на Python с YOLO и OpenCV
AI_Generated 29.04.2025
Компьютерное зрение — одна из самых динамично развивающихся областей искусственного интеллекта. В нашем мире, где визуальная информация стала доминирующим способом коммуникации, способность машин. . .
Эффективные парсеры и токенизаторы строк на C#
UnmanagedCoder 29.04.2025
Обработка текстовых данных — частая задача в программировании, с которой сталкивается почти каждый разработчик. Парсеры и токенизаторы составляют основу множества современных приложений: от. . .
C++ в XXI веке - Эволюция языка и взгляд Бьярне Страуструпа
bytestream 29.04.2025
C++ существует уже более 45 лет с момента его первоначальной концепции. Как и было задумано, он эволюционировал, отвечая на новые вызовы, но многие разработчики продолжают использовать C++ так, будто. . .
Слабые указатели в Go: управление памятью и предотвращение утечек ресурсов
golander 29.04.2025
Управление памятью — один из краеугольных камней разработки высоконагруженных приложений. Го (Go) занимает уникальную нишу в этом вопросе, предоставляя разработчикам автоматическое управление памятью. . .
Разработка кастомных расширений для компилятора C++
NullReferenced 29.04.2025
Создание кастомных расширений для компиляторов C++ — инструмент оптимизации кода, внедрения новых языковых функций и автоматизации задач. Многие разработчики недооценивают гибкость современных. . .
Гайд по обработке исключений в C#
stackOverflow 29.04.2025
Разработка надёжного программного обеспечения невозможна без грамотной обработки исключительных ситуаций. Любая программа, независимо от её размера и сложности, может столкнуться с непредвиденными. . .
Создаем RESTful API с Laravel
Jason-Webb 28.04.2025
REST (Representational State Transfer) — это архитектурный стиль, который определяет набор принципов для создания веб-сервисов. Этот подход к построению API стал стандартом де-факто в современной. . .
Дженерики в C# - продвинутые техники
stackOverflow 28.04.2025
История дженериков началась с простой идеи — создать механизм для разработки типобезопасного кода без потери производительности. До их появления программисты использовали неуклюжие преобразования. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru