unit Unit1; {$mode objfpc}{$H+} interface uses Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls; type { Драконова ломаная Чтобы ее нарисовать мы начинае с одного отрезка. Одна из точек этого отрезка это точка сгиба. Чтобы "разогнуть" этот отрезок нам нужно нарисовать все что находится по одну сторону от точки сгиба на другой стороне, но под углом в 90 градусов. } { TForm1 } TForm1 = class(TForm) EditK: TEdit; StartStopBtn: TButton; Screen: TPaintBox; procedure ScreenPaint(Sender: TObject); procedure StartStopBtnClick(Sender: TObject); private var x, y: Integer; { Положение "черепашки" } angle: Real; { и ее направление } pen: Boolean; { Режим работы (рисовать/не рисовать) } turns: array of Real; public procedure TURTLE_INIT; { Инициализация } procedure GO(distance: Integer); { Пройти distance пикселов по прямой } procedure TURN(a: Real); { Повернуться на угол a } procedure PEN_UP; { Поднять карандаш (не рисовать) } procedure PEN_DOWN; { Опустить карандаш (рисовать) } end; var Form1: TForm1; implementation {$R *.lfm} procedure TForm1.StartStopBtnClick(Sender: TObject); var i, oldIndex, oldSize, newSize, k, j: Integer; begin { Длина массива 2 ^ (k - 1) } oldSize := 1; // k = 1 turns := [0]; k := StrToInt(EditK.Text); if k > 1 then begin for j := 2 to k do begin newSize := oldSize * 2; SetLength(turns, newSize); oldIndex := oldSize - 1; turns[oldSize] := -90; for i := oldSize + 1 to newSize - 1 do begin turns[i] := -turns[oldIndex]; oldIndex := oldIndex - 1; end; oldSize := newSize; end; end; Screen.Invalidate; Sleep(10); Application.ProcessMessages; end; procedure TForm1.ScreenPaint(Sender: TObject); var i: Real; begin TURTLE_INIT; GO(Screen.Height div 2); Turn(-90); Go(Screen.Width div 2); Turn(90); PEN_DOWN; for i in turns do begin Turn(i); GO(50); end; PEN_UP; end; procedure TForm1.TURTLE_INIT; begin x := 0; { Начальное положение - левый } y := Screen.Height; { нижний угол } angle := PI / 2; { Начальное направление - "вверх" } Screen.Canvas.Pen.Color := clGreen; Screen.Canvas.MoveTo(x, y); end; procedure TForm1.GO(distance: Integer); var newx, newy: Integer; begin newx := x + Round(distance * Cos(angle)); newy := y - Round(distance * Sin(angle)); if pen = true then Screen.Canvas.LineTo(newx, newy) else Screen.Canvas.MoveTo(newx, newy); x := newx; y := newy; end; procedure TForm1.TURN(a: Real); begin { Используем формулу радианы = градусы * PI / 180 } angle := angle + a * PI / 180; end; procedure TForm1.PEN_UP; begin pen := false; end; procedure TForm1.PEN_DOWN; begin pen := true; end; end.