unit Main;
interface
uses
...
const
Größe = 250.0;
MaxHeight = 240;
Dauer = 1;
Dicke = 25;
type
TZug =
record
Von, Nach: integer;
constructor Create( AVon, ANach: integer );
end;
TKindOfAnimation = ( Up, RightOrLeft, Down, Next );
TForm128 =
class( TForm )
..
private
{ Private-Deklarationen }
Scheiben :
array of TRectangle;
Pole :
array [ 1 .. 3 ]
of TPointF;
Stange :
array [ 1 .. 3 ]
of TStack<integer>;
Colors :
array [ 0 .. 9 ]
of TAlphaColor;
Zugliste : TQueue<TZug>;
ScheibenNr : integer;
AktAnimation: TKindOfAnimation;
AktZug : TZug;
procedure Init(
const AAnzahl: integer );
procedure DeInit;
procedure dohanoi( Anzahl, AFrom, ATo, ASave: integer );
procedure ShowZüge;
function GetZug(
out AZug: TZug ): boolean;
procedure ShowZug( AZug: TZug );
procedure Animation( AKind: TKindOfAnimation );
function GetColor( A, B: integer ): TAlphaColor;
public
{ Public-Deklarationen }
end;
implementation
{$R *.fmx}
procedure TForm128.dohanoi( Anzahl, AFrom, ATo, ASave: integer );
begin
if Anzahl > 0
then
begin
dohanoi( Anzahl - 1, AFrom, ASave, ATo );
Zugliste.Enqueue( TZug.Create( AFrom, ATo ) );
dohanoi( Anzahl - 1, ASave, ATo, AFrom );
end
end;
procedure TForm128.FloatAnimation1Finish( Sender: TObject );
begin
AktAnimation := Succ( AktAnimation );
if AktAnimation = Next
then
begin
Application.ProcessMessages;
ShowZüge;
end
else
Animation( AktAnimation );
end;
procedure TForm128.FormCreate( Sender: TObject );
begin
Colors[ 0 ] := TAlphaColorRec.Black;
Colors[ 1 ] := TAlphaColorRec.Darkviolet;
Colors[ 2 ] := TAlphaColorRec.Blue;
Colors[ 3 ] := TAlphaColorRec.Deepskyblue;
Colors[ 4 ] := TAlphaColorRec.Mediumseagreen;
Colors[ 5 ] := TAlphaColorRec.Greenyellow;
Colors[ 6 ] := TAlphaColorRec.Yellow;
Colors[ 7 ] := TAlphaColorRec.Orange;
Colors[ 8 ] := TAlphaColorRec.Orangered;
Colors[ 9 ] := TAlphaColorRec.Red;
Setlength( Scheiben, 0 );
TrackBar1.Value := Dauer * 1000;
Stange[ 1 ] := TStack<integer>.Create;
Stange[ 2 ] := TStack<integer>.Create;
Stange[ 3 ] := TStack<integer>.Create;
Pole[ 1 ].X := Leftpole.Position.X + ( Leftpole.Width / 2 );
Pole[ 2 ].X := MidPole.Position.X + ( MidPole.Width / 2 );
Pole[ 3 ].X := RightPole.Position.X + ( RightPole.Width / 2 );
Init( trunc( SpinBox1.Value ) );
end;
function TForm128.GetColor( A, B: integer ): TAlphaColor;
var
M: Single;
begin
if A = 0
then
Exit( Colors[ 0 ] );
if A = B
then
Exit( Colors[ 9 ] );
M := ( 9 / B ) * A;
Result := Colors[ trunc( M ) ];
end;
function TForm128.GetZug(
out AZug: TZug ): boolean;
begin
if Zugliste.Count > 0
then
begin
AZug := Zugliste.Dequeue;
Result := true;
end
else
Result := false;
end;
procedure TForm128.Animation( AKind: TKindOfAnimation );
begin
AktAnimation := AKind;
case AKind
of
Up:
begin
FloatAnimation1.Stop;
FloatAnimation1.Parent := Scheiben[ ScheibenNr ];
FloatAnimation1.StartValue := Scheiben[ ScheibenNr ].Position.Y;
FloatAnimation1.StopValue := MaxHeight;
FloatAnimation1.AnimationType := TAnimationType.&
In;
FloatAnimation1.Interpolation := TInterpolationType.Quadratic;
FloatAnimation1.Start;
end;
RightOrLeft:
begin
FloatAnimation2.Stop;
FloatAnimation2.Parent := Scheiben[ ScheibenNr ];
FloatAnimation2.StartValue := Scheiben[ ScheibenNr ].Position.X;
FloatAnimation2.StopValue := Pole[ AktZug.Nach ].X - ( Scheiben[ ScheibenNr ].Width / 2 );
FloatAnimation2.Start;
end;
Down:
begin
FloatAnimation1.Stop;
FloatAnimation1.Parent := Scheiben[ ScheibenNr ];
FloatAnimation1.StartValue := MaxHeight;
FloatAnimation1.StopValue := Ground.Position.Y - ( Stange[ AktZug.Nach ].Count * Dicke );
FloatAnimation1.AnimationType := TAnimationType.
Out;
FloatAnimation1.Interpolation := TInterpolationType.Bounce;
FloatAnimation1.Start;
end;
end;
// of case
end;
procedure TForm128.Button1Click( Sender: TObject );
begin
Button1.Enabled := false;
SpinBox1.Enabled := false;
Application.ProcessMessages;
Init( trunc( SpinBox1.Value ) );
Zugliste := TQueue<TZug>.Create;
dohanoi( trunc( SpinBox1.Value ), 1, 3, 2 );
ShowZüge;
end;
procedure TForm128.DeInit;
begin
Zugliste.Free;
FloatAnimation1.Parent :=
nil;
FloatAnimation2.Parent :=
nil;
Button1.Enabled := true;
SpinBox1.Enabled := true;
end;
procedure TForm128.Init(
const AAnzahl: integer );
var
i : integer;
StartSize, StartStack, DeltaW: Single;
begin
Stange[ 1 ].Clear;
Stange[ 2 ].Clear;
Stange[ 3 ].Clear;
for i := 0
to high( Scheiben )
do
Scheiben[ i ].Free;
StartSize := Größe;
StartStack := Ground.Position.Y - Dicke;
Setlength( Scheiben, AAnzahl );
FloatAnimation1.Duration := TrackBar1.Value / 1000;
FloatAnimation2.Duration := TrackBar1.Value / 1000;
DeltaW := 230 / AAnzahl;
for i := 0
to AAnzahl - 1
do
begin
Scheiben[ i ] := TRectangle.Create( Self );
Scheiben[ i ].Parent := Layout1;
Scheiben[ i ].Height := Dicke;
Scheiben[ i ].Width := StartSize;
Scheiben[ i ].Position.X := Pole[ 1 ].X - ( StartSize / 2 );
Scheiben[ i ].Position.Y := StartStack;
Scheiben[ i ].Fill.Color := GetColor( i, AAnzahl - 1 );
StartStack := StartStack - Dicke;
StartSize := StartSize - DeltaW;
Stange[ 1 ].Push( i );
end;
end;
procedure TForm128.ShowZug( AZug: TZug );
begin
ScheibenNr := Stange[ AZug.Von ].Pop;
Stange[ AZug.Nach ].Push( ScheibenNr );
AktZug := AZug;
Animation( Up );
end;
procedure TForm128.ShowZüge;
var
Zug: TZug;
begin
if GetZug( Zug )
then
ShowZug( Zug )
else
DeInit;
end;
{ TZug }
constructor TZug.Create( AVon, ANach: integer );
begin
Von := AVon;
Nach := ANach;
end;
end.