140 lines
3.2 KiB
ObjectPascal
140 lines
3.2 KiB
ObjectPascal
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.
|
||
|