Add book "Занимательное программирование"
This commit is contained in:
139
Занимательное программирование/1/10_turtle/unit1.pas
Normal file
139
Занимательное программирование/1/10_turtle/unit1.pas
Normal file
@@ -0,0 +1,139 @@
|
||||
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.
|
||||
|
||||
Reference in New Issue
Block a user