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.
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
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
Neue Lösung hinzufügen
Bewertung
Durchschnittliche Bewertung:
Meta
Zeit: | 1 |
Schwierigkeit: | k.A. |
Webcode: | fk8y-npoa |
Autor: | Martin Guggisberg (Universität Basel / PH FHNW) |
Kommentare (1)