Einzelnen Beitrag anzeigen

Hanoi1

Registriert seit: 12. Feb 2016
11 Beiträge
 
#1

Grafische Lösung der Türme von Hanoi (Rekursion)

  Alt 12. Feb 2016, 21:09
Hallo!

Ich arbeite gerade an den berühmten Türmen und versuche, eine grafische Umsetzung des rekursiven Algorithmus mittels Shapes zu programmieren.
Das ist mir bisher in soweit gelungen, dass das Problem gelöst wurde, aber keine Bewegung sichtbar war.

Das wollte ich durch die sleep(...)-Funktion verbessern, sodass wenigstens Pausen zwischen den Sprüngen sind - jedoch vergeblich...
Nach dem Klick auf Button2 ist nun eine lange Pause und danach "hüpft" der Turm in die Lösungsposition.

Hier mein Quelltext (er ist teilweise wahrscheinlich ziemlich umständlich, aber eins nach dem anderen!):


Code:
[DELPHI]
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  ExtCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Edit1: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    PaintBox1: TPaintBox;
    Links: Tshape;
    Rechts: Tshape;
    Mitte: Tshape;
    Shape1: TShape;
    Shape2: TShape;
    Shape3: TShape;
    Shape4: TShape;
    Shape5: TShape;
    Shape6: TShape;
    Shape7: TShape;
    Shape8: TShape;
    Shape9: TShape;
    Shape10: TShape;
    ShapeMOVE: TShape;
    TA: TShape;
    TB: TShape;
    TC: TShape;
    ShapeMF: TShape;
    ShapeMT: TShape;
    Timer1: TTimer;
    Timer2: TTimer;
    Timer3: TTimer;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure draw(a,b,c,d: integer; n: string);
var Shape : TShape;
begin
 Shape := TShape.Create(Form1);
 With Shape do
  begin
   Parent := Form1;
   Left := a;
   Top := b;
   Width:= c;
   Height:=d;
   Name := n;
  end;
end;

procedure counterLplus;
begin
  Form1.Label2.caption:= IntToStr(StrToInt(Form1.Label2.Caption)+1);
end;

procedure counterMplus;
begin
  Form1.Label3.caption:= IntToStr(StrToInt(Form1.Label3.Caption)+1);
end;

procedure counterRplus;
begin
  Form1.Label4.caption:= IntToStr(StrToInt(Form1.Label4.Caption)+1);
end;

procedure counterLminus;
begin
  Form1.Label2.caption:= IntToStr(StrToInt(Form1.Label2.Caption)-1);
end;

procedure counterMminus;
begin
  Form1.Label3.caption:= IntToStr(StrToInt(Form1.Label3.Caption)-1);
end;

procedure counterRminus;
begin
  Form1.Label4.caption:= IntToStr(StrToInt(Form1.Label4.Caption)-1);
end;

procedure Ground(e,f: integer);
begin
 draw(100,550,e,f,'Links');
 draw(400,550,e,f,'Mitte');
 draw(700,550,e,f,'Rechts');
end;

procedure towerA(t: integer);
var i,z,x,y,w,h: integer; g: string;
begin
 i:=0;
 z:=t+1;
 repeat
 begin
  i:=i+1;
  z:=z-1;
  x:=100+((i-1)*10);
  y:=550-(i*50);
  w:=200-((i-1)*20);
  h:=50;
  g:='Shape'+IntToStr(z);
  draw(x,y,w,h,g);
 end;
 until i=t;
end;

procedure define(l: integer);
begin
 if l=1 then
 begin
 Form1.ShapeMOVE:=Form1.Shape1;
 end;
 if l=2 then
 begin
 Form1.ShapeMOVE:=Form1.Shape2;
 end;
 if l=3 then
 begin
 Form1.ShapeMOVE:=Form1.Shape3;
 end;
 if l=4 then
 begin
 Form1.ShapeMOVE:=Form1.Shape4;
 end;
 if l=5 then
 begin
 Form1.ShapeMOVE:=Form1.Shape5;
 end;
 if l=6 then
 begin
 Form1.ShapeMOVE:=Form1.Shape6;
 end;
 if l=7 then
 begin
 Form1.ShapeMOVE:=Form1.Shape7;
 end;
 if l=8 then
 begin
 Form1.ShapeMOVE:=Form1.Shape8;
 end;
 if l=9 then
 begin
 Form1.ShapeMOVE:=Form1.Shape9;
 end;
 if l=10 then
 begin
 Form1.ShapeMOVE:=Form1.Shape10;
 end;
end;

procedure undefine(l: integer);
begin
 if l=1 then
 begin
 Form1.Shape1:=Form1.ShapeMOVE;
 end;
 if l=2 then
 begin
 Form1.Shape2:=Form1.ShapeMOVE;
 end;
 if l=3 then
 begin
 Form1.Shape3:=Form1.ShapeMOVE;
 end;
 if l=4 then
 begin
 Form1.Shape4:=Form1.ShapeMOVE;
 end;
 if l=5 then
 begin
 Form1.Shape5:=Form1.ShapeMOVE;
 end;
 if l=6 then
 begin
 Form1.Shape6:=Form1.ShapeMOVE;
 end;
 if l=7 then
 begin
 Form1.Shape7:=Form1.ShapeMOVE;
 end;
 if l=8 then
 begin
 Form1.Shape8:=Form1.ShapeMOVE;
 end;
 if l=9 then
 begin
 Form1.Shape9:=Form1.ShapeMOVE;
 end;
 if l=10 then
 begin
 Form1.Shape10:=Form1.ShapeMOVE;
 end;
end;

procedure movetop(r: integer;ShapeMF,ShapeMT: TShape);
begin
 define(r);
 Form1.ShapeMOVE.left:=ShapeMT.left+((200-Form1.ShapeMOVE.width)DIV 2);
 if ShapeMT.left=Form1.Mitte.left then
 begin
    counterMplus;
    Form1.ShapeMove.top:=550-((StrToInt(Form1.Label3.caption))*50);
 end;
 if ShapeMT.left=Form1.Links.left then
 begin
    counterLplus;
    Form1.ShapeMove.top:=550-((StrToInt(Form1.Label2.caption))*50);
 end;
 if ShapeMT.left=Form1.Rechts.left then
 begin
    counterRplus;
    Form1.ShapeMove.top:=550-((StrToInt(Form1.Label4.caption))*50);
 end;
 if ShapeMF.left=Form1.Mitte.left then
 begin
    counterMminus;
 end;
 if ShapeMF.left=Form1.Links.left then
 begin
    counterLminus;
 end;
 if ShapeMF.left=Form1.Rechts.left then
 begin
    counterRminus;
 end;
 sleep(1000);
 undefine(r);
end;        

procedure rec(r: integer;TA,TB,TC: TShape);
begin
 if r>0 then
 begin
   rec(r-1,TA,TC,TB);
   movetop(r,TA,TC);
   rec(r-1,TB,TA,TC);
 end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var k: Integer;
begin
 k:=StrToInt(Edit1.Text);
 Label1.caption:= 'Scheiben';
 Label2.caption:= IntToStr(k);
 Label3.caption:= IntToStr(0);
 Label4.caption:= IntToStr(0);
 Ground(200,50);
 towerA(k);
end;

procedure TForm1.Button2Click(Sender: TObject);
var k: Integer;
begin
 k:=StrToInt(Edit1.Text);
 rec(k,Links,Mitte,Rechts);
end;
[DELPHI]
Ich dachte über eine Lösung mittels Timer nach. Macht das vielleicht mehr Sinn? Falls ja, wie bewirke ich, dass das Heuptprogramm, während der Timer läuft, stillsteht?

Vielen Dank im Voraus!

LG

Geändert von Hanoi1 (12. Feb 2016 um 23:16 Uhr)
  Mit Zitat antworten Zitat