Buch Cover Buch Cover Buch Cover Buch Cover

Web-Code: - Webcode Help

Türme von Hanoi (Rekursion)

Dieses SpielDas Spiel der "Türme von Hanoi" wurde erstmals publiziert vom Mathematiker Édouard Lucas (1842 - 1891) besteht aus drei Stäben A, B und C, auf welche mehrere gelochte Scheiben gelegt werden. Alle Scheiben sind verschieden groß. Zu Beginn liegen alle Scheiben der Größe nach auf Stab A (kleinste Scheibe oben). Ziel des Spiels ist es, den kompletten Stapel von A nach C zu versetzen.

Spielposition bei Türme von Hanoi

Bei jedem Zug darf nur die oberste Scheibe eines beliebigen Stabes auf einen der beiden anderen Stäbe gelegt werden -- vorausgesetzt, dort liegt nicht schon eine kleinere Scheibe. Folglich sind zu jedem Zeitpunkt des Spiels die Scheiben auf jedem Stab der Größe nach geordnet.

Erstellen Sie ein Programm, welches die einzelnen Schritte zum Verschieben eines aus fünf Scheiben bestehenden Turmes von A nach C beschreibt.

1 Kommentare

Bitte melde dich an um einen Kommentar abzugeben

Kommentare (1)

Adrian_Wetzel69 15. Mai 2017 13:23   reply report
ich finde diese Aufgabe sehr interessant. wänd sie au mol riebe ┌П┐(◉_◉)┌П┐?

7 Lösung(en)

public class Tuerme_von_Hanoi
{
  /** 
   * Bewegt n Scheiben von Turm a nach Turm c und benutzt als 
   * Zwischenspeicher Turm b. 
   */ 
  public void bewege (char a, char b, char c, int n) { 
    if (n == 1) {
      System.out.println(a + " -> " + c ); } 
    else { 
      bewege(a, c, b, n-1); 
      bewege(a, b, c, 1); 
      bewege(b, a, c, n-1); } 
  }

  public static void main (String[] args) {
    new Tuerme_von_Hanoi().bewege('a', 'b', 'c', 5); }
   
}
                
function bewege(a, b, c, n)
// Bewegt n Scheiben von Turm a nach Turm c und benutzt als Zwi-
// schenspeicher Turm b.
{
    if (n == 1)
	document.writeln(a + " -> " + c );
    else {
	bewege(a, c, b, n-1);
	bewege(a, b, c, 1);
	bewege(b, a, c, n-1);
    }
}

document.writeln("<html><body><pre>");
bewege("a", "b", "c", 5);
document.writeln("</body></html>");
                
#!/usr/bin/perl
use strict;

sub bewege
# Bewegt n Scheiben von Turm a nach Turm c und benutzt als Zwi-
# schenspeicher Turm b.
{
    my ($a, $b, $c, $n) = @_;
    if ($n == 1) {
        print "$a -> $b.\n";
    } else {
        bewege($a, $c, $b, $n-1);
        bewege($a, $b, $c, 1);
        bewege($b, $a, $c, $n-1);
    }
}

bewege("a", "b", "c", 5);

__END__                        
                
#Tuerme_von_Hanoi
def bewege (n, a='a', b='b', c='c'):  
   if n == 1: 
 	  print repr(a) + ' -> ' + repr(c)  
   else:  
   	bewege(n-1, a, c, b) 
   	bewege(1, a, b, c)
   	bewege(n-1, b, a, c) 

bewege(5); 
                
public class HanoiIterativ {
    public static void main(String[] args) {
        new HanoiIterativ().top();    }

    int                 ANZAHL_SCHEIBEN    = 5;
    LinkedList<Integer> staebe[]           = new LinkedList[3];
    int                 posKleinsteScheibe = 0;

    void top() {
        initStaebe();
        int drehrichtung = 1; // in welche Richtung wandert die kleinste Scheibe immer.
        if (geradeAnzahl()) {
            drehrichtung = -1; }
        while (!ende()) {
            moveKleinste(drehrichtung);
            if (!ende())
                moveAndere();
        }
    }

    /**
     * Finde kleinere Scheibe der beiden Türme, die nicht von der kleinsten
     * Scheibe bedeckt sind. Nun, verschiebe nach Regel.
     */
    void moveAndere() {
        if (0 == posKleinsteScheibe) {
            moveKleinere(1, 2);
            return;        }
        if (1 == posKleinsteScheibe) {
            moveKleinere(0, 2);
            return;        }
        // 2 == posKleinsteScheibe
        moveKleinere(0, 1);
    }

    void moveKleinere(int erste, int zweite) {
        if (0 == staebe[erste].size()) {
            move(zweite, erste);
            return;        }
        if (0 == staebe[zweite].size()) {
            move(erste, zweite);
            return;        }
        if (staebe[erste].getLast() < staebe[zweite].getLast()) {
            move(erste, zweite);
        } else {
            move(zweite, erste);        }
    }

    void move(int posVon, int posNach) {
        System.out.println("move " + posVon + "  -> " + posNach);
        staebe[posNach].add(staebe[posVon].removeLast());    }

    private void moveKleinste(int richtung) {
        // finde stockwerk
        int posVon = posKleinsteScheibe;
        int posNach = (posVon + richtung + 3) % 3;
        move(posVon, posNach);
        posKleinsteScheibe = posNach;    }

    boolean ende() { // Alle auf Stab 1 (begonnen wurde bei Stab 0)
        return ANZAHL_SCHEIBEN == staebe[1].size();    }

    boolean geradeAnzahl() {
        return 0 == ANZAHL_SCHEIBEN % 2;    }

    /**
     * Fülle "ANZAHL_SCHEIBEN" auf den ersten Stab.
     */
    private void initStaebe() {
        int stab = 0;
        while (stab < 3) {
            staebe[stab] = new LinkedList<Integer>();
            stab = stab + 1;        }
        int stockwerk = 0;
        while (stockwerk < ANZAHL_SCHEIBEN) {
            staebe[0].add(ANZAHL_SCHEIBEN - stockwerk);
            stockwerk = stockwerk + 1;        }
    }

} // end of class HanoiIterativ
                
(*---------------------------------------------------------------------
    :Program.    Hanoi2
    :Author.     Philippe Gressly
    :Address.    Näfenhaus, CH-8926 Kappel a/Albis
    :Phone.
    :Shortcut.   [Philu]
    :Version.    1.0
    :Date.       9.1990
    :Copyright.  PD
    :Language.   Modula-II
    :Translator. M2Amiga
    :Imports.    Str, DosConWin(Philu), Arts
    :UpDate
    :Contents.   Eine Lösung des Turms von Hanoi.
    :Remark.
---------------------------------------------------------------------*)

MODULE Hanoi2;

FROM InOut IMPORT WriteString, WriteLn, WriteInt, ReadInt, Read, Write;
FROM Str IMPORT Copy, Concat;
FROM Dos IMPORT Delay, Output;
IMPORT Terminal;
FROM Intuition IMPORT WindowPtr;
FROM Graphics IMPORT RastPortPtr, SetAPen, RectFill;
FROM DosWinSupport IMPORT DosWinToIntui, ActionResult;
FROM SYSTEM IMPORT ADR;
FROM Arts IMPORT Assert;




CONST MaxHoehe = 20;


VAR Tuerme : ARRAY[1..3],[1..MaxHoehe] OF INTEGER;
             (* Null bedeutet, da ist kein Turm,
              * die Zahlen geben die Durchmesser der Scheiben an.
              *)
    TurmZahlen : ARRAY[1..3] OF INTEGER;
              (* Wieviele Scheiben liegen auf den Türmen *)
    StartHoehe: INTEGER;
    Waiter    : INTEGER; (* Sagt, wie lange nach einer Verschiebung gewartet
                          * werden soll.
                          *)
    MyWPtr    : WindowPtr;
    MyRPortPtr: RastPortPtr;
    Ende      : BOOLEAN; (* Sagt, ob ein Turmbau unterbrochen wurde. *)



 (*-------------- P R O C E D U R E ----------------)
 |
 | Name    : IntToStr
 | Input   : X: INTEGER zu konvertieren
 | Output  : XS: ErgebnisString
 | Proc    : Wandelt eine positive INTEGER-Zahl in einen 4-Byte-String
 | Function: NO
 | Global  : Ord0 ( ORD("0")) (VAR)
 | Special :
 |
 | Author  : Philu
 +------------------------------------------------*)
CONST Ord0 = ORD("0");
PROCEDURE IntToStr(X: INTEGER; VAR  XS: ARRAY OF CHAR);
BEGIN
   XS[0] := CHR(((X MOD   1000) DIV   100) + Ord0);
   XS[1] := CHR(((X MOD    100) DIV    10) + Ord0);
   XS[2] := CHR(( X MOD     10)            + Ord0);
   XS[3] := CHR(0)
END IntToStr;



(*-------------- P R O C E D U R E ----------------)
 |
 | Name    : GotoXY
 | Input   : X,Y: Position in Spalten(X) und Zeilen(Y)
 | Output  :
 | Proc    : Setzt den Cursor an X,Y-Position
 | Function: NO
 | Global  : IntToStr (PRC)
 | Special :
 |
 | Author  : Philu
 +------------------------------------------------*)
PROCEDURE GotoXY(X,Y: INTEGER);
VAR XStr, YStr: ARRAY [0..6] OF CHAR;
    ConStr: ARRAY[0..12] OF CHAR;
BEGIN
   IntToStr(X, XStr);
   IntToStr(Y, YStr);
   ConStr[0] := CHR(09BH);
   ConStr[1] := CHR(0);
   Concat(ConStr, YStr);
   Concat(ConStr, ";");
   Concat(ConStr, XStr);
   Concat(ConStr, "H");
   WriteString(ConStr)
END GotoXY;



 (*-------------- P R O C E D U R E ----------------)
 |
 | Name    : InitBrett
 | Input   : Hoehe der Tuerme
 | Output  :
 | Proc    : Initialisiert die Globalen Datenstruktuen Tuereme,
 |           und Turmzahlen
 | Function: NO
 | Global  : Tuerme     (VAR)
 |           TurmZahlen (VAR)
 |           MaxHoehe   (VAR)
 | Special :
 |
 | Author  : Philu
 +------------------------------------------------*)
PROCEDURE InitBrett(Hoehe: INTEGER);
VAR i,j: INTEGER;
BEGIN
   FOR j := 1 TO 3 DO
      FOR i := 1 TO MaxHoehe DO
         IF (j = 1) AND (1 <= Hoehe) THEN
            Tuerme[j,i] := Hoehe - i + 1
         ELSE
            Tuerme[j,i] := 0
         END
      END;
      TurmZahlen[j] := 0
   END;
   TurmZahlen[1] := Hoehe
END InitBrett;



(*-------------- P R O C E D U R E ----------------)
 |
 | Name    : PaintScheibe
 | Input   : TurmNr: Nummer des Turmes, wo die Scheibe zu zeichnen
 |           Hoehe:  In welcher Hoehe ist die Scheibe zu zeichnen
 | Output  :
 | Proc    : Zeichnet die Scheibe, deren Dicke in Tuerme
 |           abgespeichert ist.
 |           Bemerkung: die Procedur zeichnet automatisch einen "Pfeiler"
 |           für die Scheiben, da die Dicke 0 für ein Rechteck nicht gültig
 |           ist. Ich brauche also keine Abfrage einzubauen wie
 |           IF Breite # 0 THEN ...
 | Function: NO
 | Global  : StartHoehe (VAR)
 |           Tuerme     (VAR)
 | Special :
 |
 | Author  : Philu
 +------------------------------------------------*)
CONST DX = 4; DY = 3; DYme = DY - 1; BT = 5;
PROCEDURE PaintScheibe(TurmNr, Hoehe: INTEGER);
VAR X, Y, Breite: INTEGER;
BEGIN (* PaintScheibe *)
   X := 10     + (TurmNr-1) * (2 * StartHoehe * DX + BT);
   Y := 25 + (StartHoehe - Hoehe) * DY;
   Breite := Tuerme[TurmNr, Hoehe];
   SetAPen(MyRPortPtr, 0);
   RectFill(MyRPortPtr,
            X,
            Y,
            X + 1 + 2 * StartHoehe * DX,
            Y + DYme);
   SetAPen(MyRPortPtr, Breite MOD 3 + 1);
   RectFill(MyRPortPtr,
            X + (StartHoehe - Breite) * DX,
            Y,
            X + (StartHoehe + Breite) * DX,
            Y + DYme)
END PaintScheibe;



(*-------------- P R O C E D U R E ----------------)
 |
 | Name    : RemoveScheibe
 | Input   : TurmNr: Nummer des Turmes, dessen oberste Scheibe zu
 |                   entfernen ist.
 | Output  : Dicke der Scheibe
 | Proc    : Entfernt die oberste Scheibe auf TurmNr,
 |           zeichnet das ganze und gibt die Dicke des
 |           entfernten Steins zurück.
 | Function: YES
 | Global  : Tuerme       (VAR)
 |           TurmZahlen   (VAR)
 |           PaintScheibe (PRC)
 | Special :
 |
 | Author  : Philu
 +------------------------------------------------*)
PROCEDURE RemoveScheibe(TurmNr: INTEGER):INTEGER;
(* Gibt als Resultat die Dicke der Scheibe zurück *)
VAR Dicke: INTEGER;
BEGIN (* RemoveScheibe *)
   Dicke := Tuerme[TurmNr, TurmZahlen[TurmNr]];
   Tuerme[TurmNr, TurmZahlen[TurmNr]] := 0;
   PaintScheibe(TurmNr, TurmZahlen[TurmNr]);
   DEC(TurmZahlen[TurmNr]);
   RETURN Dicke
END RemoveScheibe;



(*-------------- P R O C E D U R E ----------------)
 |
 | Name    : SetScheibe
 | Input   : Wohin: Auf welchen Turm ist die Scheibe zu setzen.
 |           Dicke: Wie dick ist die zu setzende Scheibe.
 | Output  :
 | Proc    : Setzt eine Scheibe der Dicke "Dicke" auf den Turm "Wohin"
 |           und Zeichnet das ganze.
 | Function: NO
 | Global  : TurmZahlen   (VAR)
 |           Tuerme       (VAR)
 |           PaintScheibe (PRC)
 | Special :
 |
 | Author  : Philu
 +------------------------------------------------*)
PROCEDURE SetScheibe(Wohin, Dicke: INTEGER);
BEGIN
   INC(TurmZahlen[Wohin]);
   Tuerme[Wohin, TurmZahlen[Wohin]] := Dicke;
   PaintScheibe(Wohin, TurmZahlen[Wohin])
END SetScheibe;



(*-------------- P R O C E D U R E ----------------)
 |
 | Name    : PaintBrett
 | Input   :
 | Output  :
 | Proc    : Zeichnet die drei Tuerme
 | Function: NO
 | Global  : StartHoehe   (VAR)
 |           PaintScheibe (PRC)
 | Special :
 |
 | Author  : Philu
 +------------------------------------------------*)
PROCEDURE PaintBrett;
VAR j, k: INTEGER;
BEGIN
   Write(CHR(12)); (* CLS *)
   FOR k := 1 TO StartHoehe  DO
      FOR j := 1 TO 3 DO
         PaintScheibe(j, k)
      END (* FOR j *)
   END
END PaintBrett;



(*-------------- P R O C E D U R E ----------------)
 |
 | Name    : Dritt
 | Input   : A,B: Die Nummern zweier Türme
 | Output  : Die Nummer des dritten Turmes
 | Proc    : Findet zu zwei Turmnummern die freie Turmnummer.
 |           Vorausgesetzt die beiden Turmnummern A und B sind gültig
 |           und verschieden.
 | Function: YES
 | Global  :
 | Special : Funktioniert nur bei korrekter Eingabe
 |
 | Author  : Philu
 +------------------------------------------------*)
PROCEDURE Dritt(A,B: INTEGER): INTEGER;
VAR i: INTEGER;
BEGIN
   FOR i := 1 TO 3 DO
        IF (A#i) AND (B#i) THEN RETURN i END
   END
END Dritt;



VAR ch: CHAR;



 (*-------------- P R O C E D U R E ----------------)
 |
 | Name    : Schiebe
 | Input   : Woher: Von welchem Turm wird geschoben.
 |           Wieviele: Wieviele Scheiben sollen geschoben werden.
 |                     Es werden nur die obersten Scheiben geschoben.
 |           Wohin: Auf welchen Turm sollen die Scheiben geschoben
 |                  werden.
 | Output  :
 | Proc    : - Die Procedur arbeitet rekursiv.
 |           - Hat die Procedur nur eine Scheibe zu schieben (die oberste),
 |             so ist es ganz einfach. Die Proceduren RemoveScheibe und
 |             SetScheibe nehmen in diesem Fall die ganze Arbeit ab.
 |           - Hier ist auch eingebaut, wie lange zwischen den einzelnen
 |             Verschiebungen gewartet werden soll. Oder ob auf ein RETURN
 |             gewartet werden muß.
 |           - Hat die Procedur mehrere Scheiben zu schieben, so schiebt sie
 |             einen um eins Kleineren Turm auf den noch freien Turm. Dann
 |             schiebt sie eine Scheibe auf den Zielturm. Zuletzt holt sie
 |             die Scheiben vom Dritten Turm auf den Zieltrum zurück.
 | Function: NO
 | Global  : RemoveScheibe (PRC)
 |           SetScheibe    (PRC)
 | Special : Die Procedur ruft sich selbst auf. (Rekursion)
 |
 | Author  : Philu
 +------------------------------------------------*)
PROCEDURE Schiebe(Woher, Wieviele, Wohin: INTEGER);
VAR Dr, Dicke: INTEGER;
BEGIN
   IF Wieviele = 1 THEN
      IF Waiter = -1 THEN
         IF Ende THEN RETURN END;
         GotoXY(0,0);
         WriteString("Next move 'E' for end: ");
         Read(ch);
         IF CAP(ch) = "E" THEN
            Read(ch);
            Ende := TRUE
         END;
         GotoXY(0,0)
      ELSE
         Delay(Waiter)
      END;
      Dicke := RemoveScheibe(Woher);
      SetScheibe(Wohin, Dicke)
   ELSE (* Hier mehrere Steine zu verschieben *)
      Dr := Dritt(Woher, Wohin);
      Schiebe( Woher,   Wieviele - 1,   Dr    );
      Schiebe( Woher,   1           ,   Wohin );
      Schiebe( Dr   ,   Wieviele - 1,   Wohin )
   END (* IF *)
END Schiebe;



(*-------------- P R O C E D U R E ----------------)
 |
 | Name    : HideCursor
 | Input   :
 | Output  :
 | Proc    : Macht den Cursor unsichtbar
 | Function: NO
 | Global  :
 | Special :
 |
 | Author  : Philu
 +------------------------------------------------*)
PROCEDURE HideCursor;
VAR Str: ARRAY[0..4] OF CHAR;
BEGIN
   Str[0] := CHR(09BH);
   Str[1] := CHR(030H);
   Str[2] := CHR(020H);
   Str[3] := CHR(070H);
   Str[4] := CHR(0);
   WriteString(Str)
END HideCursor;



(*-------------- P R O C E D U R E ----------------)
 |
 | Name    : Schluss
 | Input   :
 | Output  : TRUE oder FALSE, ob der Anwender Schluss machen will.
 | Proc    : Erfragt vom Anwender die Antwort auf die Frage "Schluss?".
 | Function: YES
 | Global  : GotoXY, Color
 | Special :
 |
 | Author  : Philu
 +------------------------------------------------*)
PROCEDURE Schluss(): BOOLEAN;
BEGIN
   GotoXY(0,0);
   SetAPen(MyRPortPtr, 1);
   WriteString("Schluss? (j,n) :           "); Read(ch);
   RETURN (CAP(ch) = "J") OR (CAP(ch) = "Y")
END Schluss;




BEGIN (* Hanoi2 MAIN {Hauptprogramm} *)
   Assert(ok = DosWinToIntui(Output(), MyWPtr),
          ADR("Kann Window nicht finden"));
   MyRPortPtr := MyWPtr^.rPort;
   Terminal.waitCloseGadget := FALSE;
   REPEAT (* BIS Genug gesehen (Schluss) *)
      Write(CHR(12)); (* Clear Screen *)
      REPEAT (* Hoehe einlesen bis korrekt. *)
         WriteString("Gib Höhe des Turmes:  "); ReadInt(StartHoehe);
         IF (StartHoehe < 1) OR (StartHoehe > MaxHoehe) THEN
            WriteString("Die Höhe soll zwischen 1 und ");
            WriteInt(MaxHoehe, 1);
            WriteString(" liegen."); WriteLn
         END (* IF *)
      UNTIL (StartHoehe >= 1) AND (StartHoehe <= MaxHoehe);
      REPEAT (* Wartezeit eingeben bis korrekt. *)
         WriteString("Gib Wartezeit zwischen den Verschiebungen");
         WriteLn;
         WriteString("in 1/50 Sekunden. [Gib -1 für 'Warte auf RETURN']: ");
         ReadInt(Waiter);
         IF Waiter = -1 THEN
            Ende := FALSE
         END
      UNTIL Waiter >= -1;
      InitBrett(StartHoehe);
      HideCursor;
      PaintBrett;
      GotoXY(0,0);
      IF Waiter >= 0 THEN
         WriteString("Start ... (ENTER):       ");
         Read(ch)
      END;
      Schiebe(1, StartHoehe, 2)
   UNTIL Schluss()
END Hanoi2.mod




                

Lösung von: Philipp G. Freimann (BBW (Berufsbildungsschule Winterthur) https://www.bbw.ch)

// Main.java
package application;

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;

public class Main extends Application {
	
	static int x = 0;
	
    Tower towerA = new Tower("A");
	Tower towerB = new Tower("B");
	Tower towerC = new Tower("C");
	
	final Canvas canvas = new Canvas(600,400);
	
	public static void main(String[] args) {
		launch(args);
	}
	
	@Override
	public void start(Stage primaryStage) {
		try {
			
			StackPane root = new  StackPane();
				
			drawFirstOnCanvas(canvas);
			
			Button btn = new Button("Start");
			// Button btnClear = new Button("Clear");
   		    btn.setOnAction(new EventHandler<ActionEvent>() {
		            
   		    		WorkerThread myAlgo = null; 
   		    		@Override
		            public void handle(ActionEvent event) 
		            {
   		    			if(myAlgo == null)
   		    			{
   		    				myAlgo = new WorkerThread(canvas, towerA, towerB, towerC);
   		    				myAlgo.start();
   		    			}
		            }
		        });
			root.getChildren().add(canvas);
			root.getChildren().add(btn);
			
			Scene scene = new Scene(root,640,300);
			scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
			primaryStage.setScene(scene);
			primaryStage.show();
			
		}
		catch(Exception e) 
		{
			e.printStackTrace();
		}
	}

	private void drawFirstOnCanvas(Canvas canvas)
	{
		final GraphicsContext gc = canvas.getGraphicsContext2D();
		
		// Canvas-Hintergrund als Rechteck löschen
        gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
		
		gc.setFill(Color.BLUE);
		gc.setLineWidth(2);
	
		towerA.addFirst(new Disc(20, 20));
		towerA.addFirst(new Disc(40, 20));
		towerA.addFirst(new Disc(60, 20));
		towerA.addFirst(new Disc(80, 20));
		towerA.addFirst(new Disc(100, 20));
		
		towerA.drawTower(canvas, 50, 150);
	    towerB.drawTower(canvas, 250, 150);
	    towerC.drawTower(canvas, 450, 150); 
	}
}

// Datei WorkerThread.java
package application;

import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

import javafx.application.Platform;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;

public class WorkerThread extends Thread
{
	private Canvas _canvas = null;
	
    Tower towerA = null;
	Tower towerB = null;
	Tower towerC = null;
	
	BewegeListQ bwlq = new BewegeListQ();
	
	

	public WorkerThread(Canvas canvas, Tower a, Tower b, Tower c)
	{
		setDaemon(true);
        setName("Thread_of_Algo");
		this._canvas = canvas;
		this.towerA = a;
		this.towerB = b;
		this.towerC = c;	
	}

	
	@Override
    public void run() {

		boolean isEvaluated = true;
		
        while (!isInterrupted()) 
        {
        	
        	if(isEvaluated && towerC.getDiscList().size() < towerA.getTowerSize())
			{
				bewege(towerA, towerB, towerC, towerA.getTowerSize());	
				
				isEvaluated = false;
				
				towerC.getDiscList().clear();
				towerB.getDiscList().clear();
				towerA.getDiscList().clear();
				
				towerA.addFirst(new Disc(20, 20));
				towerA.addFirst(new Disc(40, 20));
				towerA.addFirst(new Disc(60, 20));
				towerA.addFirst(new Disc(80, 20));
				towerA.addFirst(new Disc(100, 20));
			}      	
       	
            // UI updaten
            Platform.runLater(
            
            		new Runnable()
            		{
            			@Override
            			public void run() 
            			{             	          				
            				bwlq.moveStep();
            				drawTowersOfHanoi();			
            			}
            		});
          
            try 
            {
                // fuer 1 Sekunden
                sleep(TimeUnit.SECONDS.toMillis(1));
                
            } catch (InterruptedException ex) 
            {
                Logger.getLogger(WorkerThread.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
     }
	
	public void bewege(Tower a, Tower b, Tower c, int n)
	{
		if(n == 1)
		{	
			moveElement(a, c);
		}
		else
		{
			 bewege(a, c, b, n-1);
	         bewege(a, b, c, 1);
	         bewege(b, a, c, n-1);
		}
	}
	
	public void move(Tower from, Tower to)
	{
		if(from.getTowerSize() != 0)
	    {
			// record the moveStep ...
			bwlq.addStep(new Bewege(from, to));
	    	
			// move element
			to.addFirst(from.removeFirst());
	    }
	}

	public void wait(int milliseconds)
	{
		try
		{
			Thread.sleep(milliseconds);
		} 
		catch (InterruptedException e)
		{
			e.printStackTrace();
		}
	}
	
	public void moveElement(Tower from, Tower to)
	{
		
		move(from, to);
	}
	
	public void drawTowersOfHanoi()
	{
		ClearingCanvas(_canvas);
		if(towerA != null)
			towerA.drawTower(_canvas, 50, 150);
	    
		if(towerB != null)
			towerB.drawTower(_canvas, 250, 150);
	    
		if(towerC != null)
			towerC.drawTower(_canvas, 450, 150);    
	}
	
	public void ClearingCanvas(Canvas canvas)
	{
		final GraphicsContext gc = canvas.getGraphicsContext2D();
		// Canvas-Hintergrund als Rechteck löschen
        gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
	}
}

// Datei Tower.java
package application;

import java.util.LinkedList;

import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;

public class Tower
{
	private LinkedList<Disc> discs = new LinkedList<Disc>();
	private String name;
	
	public Tower()
	{

	}
	
	public Tower(String name)
	{
		this.name = name;
	}
	
	public String getName()
	{
		return this.name;
	}
	
	public LinkedList<Disc> getDiscList()
	{
		return discs;
	}

	public void drawTower(Canvas canvas, int offsetX, int offsetY)
	{
		
		final GraphicsContext gc = canvas.getGraphicsContext2D();
	
		int x = offsetX;
		int y = offsetY;
		int Xmiddle = 0;
		int Xwidest=0;
		
		for(int i =0;i<discs.size();i++)
		{	
			if(Xwidest < discs.get(i).getWidth() )
			{
				Xwidest = discs.get(i).getWidth();	
			}
		}
		
		Xmiddle = x + Xwidest / 2;
		
		
		for(int i =0;i<discs.size();i++)
		{	
			x = Xmiddle  -  (discs.get(i).getWidth()/2);  //  - (discs.get(i).getWidth()/2);
			gc.strokeRect(x ,y , discs.get(i).getWidth() , discs.get(i).getHeigth());
			y = y - discs.get(i).getHeigth();
		}
	}
	
	public int getTowerSize()
	{
		return this.discs.size();
	}


	public Disc removeFirst()
	{
		Disc disc = this.discs.removeFirst();
		return disc;
	}
	
	public Disc removeLast()
	{
		Disc disc = this.discs.removeLast();
		return disc;	
	}
	
	public void addFirst(Disc disc)
	{
		discs.addFirst(disc);
	}

	public void addLast(Disc disc)
	{
		discs.addLast(disc); 
	}
}

// Datei Disc.java
package application;

public class Disc
{
	private int width;
	private int heigth;

	
	public Disc(int width, int heigth)
	{
		this.width = width;
		this.heigth = heigth;
	}
	
	public int getWidth()
	{
		return width;
	}
	
	public void setWidth(int width)
	{
		this.width = width;
	}
	
	public int getHeigth()
	{
		return heigth;
	}
	
	public void setHeigth(int heigth)
	{
		this.heigth = heigth;
	}
}

// Datei BewegeList.java
package application;

import java.util.LinkedList;

public class BewegeListQ
{
	LinkedList<Bewege> bewegeListQ = new LinkedList<Bewege>();
	Boolean isPrinted = false;
	
	public void addStep(Bewege step)
	{
		bewegeListQ.add(step);
	}
	
	public void printSteps()
	{
		
		if(!isPrinted)
		{
			for(Bewege step:bewegeListQ)
			{
				System.out.println("--> move from "+ step.getSource() +" to "+ step.getTarget());
			}
			isPrinted = true;
		}	
	}

	public void printStep()
	{
		if(bewegeListQ.size() != 0)
		{
			Bewege step = bewegeListQ.removeFirst();
			System.out.println("--> move from "+ step.getSource() +" to "+ step.getTarget());
		}
		
	}

	public void moveStep()
	{
		Tower source = null;
		Tower target = null;
		
		if(bewegeListQ.size() != 0)
		{
			Bewege step = bewegeListQ.removeFirst();
			
			source = step.getSource();
		    target = step.getTarget();
		    
		    // remove item
		    Disc item = source.removeLast();
	    	
	    	// add item
	    	target.addLast(item);
		    		
			System.out.println("--> move from "+ step.getSource().getName() +" to "+ step.getTarget().getName());

		}
	}
}


class Bewege
{
	private Tower source = null;
	private Tower target = null;
	
	public Bewege(Tower source, Tower target)
	{
		this.source = source;
		this.target = target;
	}
	
	public Tower getSource()
	{
		return this.source;
	}
	
	public Tower getTarget()
	{
		return this.target;
	}
}
                

Lösung von: David Zeindler ()

Verifikation/Checksumme:

Die ersten drei Züge (falls n ungerade) sind:

a -> c

a -> b

c -> b

 

Aktionen

Bewertung

Durchschnittliche Bewertung:

Eigene Bewertung:
Bitte zuerst anmelden

Meta

Zeit: 1
Schwierigkeit: k.A.
Webcode: fk8y-npoa
Autor: Martin Guggisberg (Universität Basel / PH FHNW)

Download PDF

Download ZIP

Zu Aufgabenblatt hinzufügen