Türme von Hanoi - einfache grafische Ausgabe

Hallo liebe Community,

wir sollen für eine kleine Gruppenarbeit einen Algorithmus für das Spiel “Türme von Hanoi” schreiben.
Das ist ein kleines “Spiel”, bei dem man 3 Säulen hat und 2 oder mehr Scheiben von einer Säule auf eine andere verschieben soll. Dabei dürfen nur kleine auf größeren Scheiben liegen etc. Wer das Spiel nicht kennt, kann es ja mal googeln.

Naja, den Algorithmus bzw. den Code haben wir auch schon soweit fertig, allerdings sollen wir uns überlegen, wie eine einfache graphische Ausgabe auf der Konsole aussehen könnte und da kommen wir einfach nicht weiter. Mit Applets etc. haben wir noch nicht gearbeitet und ich wüsste nicht, wie ich das sonst darstellen sollte.

Hier mal der Code:


public class Hanoi {
	static long schritte;
	
	static void ausgabe (int n, String von, String nach)
	{
		System.out.printf( "Scheibe %d von %s nach %s%n", n, von, nach );
	}
	static void turmversetzen(int n, String links, String mitte, String rechts)
	{
		if (n>1)
		{
			turmversetzen(n-1, links, rechts, mitte);
			ausgabe(n,links,rechts);
			turmversetzen(n-1, mitte, links, rechts);
			}
		else ausgabe (n,links,rechts);
		schritte ++;
	}
	public static void main( String[] args ){
		Scanner scan = new Scanner(System.in);
		System.out.println("Bitte geben Sie die Anzahl der Scheiben ein: ");
		int n = scan.nextInt();
		scan.close();
		turmversetzen(n, "links", "rechts", "mitte");
		System.out.println("_______________________________________");
		System.out.println("Schritte: "+schritte);
	}
}
	

Hat vielleicht jemand eine Idee für eine simple Darstellung auf der Konsole? Bin für jede Hilfe dankbar :).

das Wort ‘Konsole’ sagt dir etwas? nix mit Applet usw., Textausgabe wie hier im Forum

überlege dir eine Darstellung wie


  |      |    |
  C      |    |
AAAAA	BBB   |

überlege dir Code der jede aktuelle Belegung korrekt darstellen kann

dann gib jeden Schritt aus mit zusätzlichen Text, aktuelle Bewegung (deine Zeile 8), Schritt-Nummer usw.,

edit: ok, zum rekursiven Gedanken mit faszinierenderweise gar nicht genauer Info zum Rest, zum Gesamtplan, passt das nicht so gut,
da müsste dann nebenher doch ein dauernd aktuallisierter Gesamtstand her,

der Code wird sich weit mehr als verdoppelt, aber anders sehe ich zumindest keine Ausgabe, da gibt es keinen 5 Zeilen-Trick, behaupte ich

*** Edit ***

Hm ja mit Arrays wäre es wohl einfacher. Wo ist denn bei deiner Ausgabe die main-Methode? Oo

habe ich Code gepostet, Arrays? main-Methode?
zum Link passt die direkte Ansprache ‚dein‘ kaum :wink:

und da gibt es ja auch eine Vielzahl Codes,
speziell dem ersten fehlt es an main-Methode, richtig,
die Ausgabe wird aber auch erst später, etwa ab #5, interessant

[QUOTE=SlaterB]habe ich Code gepostet, Arrays? main-Methode?
zum Link passt die direkte Ansprache ‚dein‘ kaum :wink:

und da gibt es ja auch eine Vielzahl Codes,
speziell dem ersten fehlt es an main-Methode, richtig,
die Ausgabe wird aber auch erst später, etwa ab #5, interessant[/QUOTE]

Sorry :P. Ich bin gerade dabei, den letzten Code zu verstehen bzw. die Ausgabe, da ich so etwas ähnliches ja benötige. Dort fehlt allerdings auch die main-Methode, dadurch bekomme ich ja auch keine Konsolenausgabe ^^

oh, und das Code-Posting war ja auch von mir,
das hatte ich nicht geplant/ erinnert, ist der einzige Link den Suchmaschinen bieten :wink:
mein Name wird ja auch schön ausgeblendet, wobei der elegante Stil natürlich unverwechselbar ist, da hast du völlig Recht :wink:

die Methode printAll() gibt den Stand aus, man ruft sie während des Programms auf, etwa in der move-Methode im Programm davor,
auf jenes bezieht sich der Code ja auch, je nach Datenstrukturen muss es anders aussehen, main-Methode und eigentliche Turm-Logik irrelevant

Die main Methode solltest du aber hinbekommen, wenn der eigentliche Algorithmus von dir/euch schon implementiert wurde.

    private static String[] tuerme;

    static void ausgabe (int n, String von, String nach)
    {
        System.out.printf( "Scheibe %d von %s nach %s%n", n, von, nach );

	tuerme[n] = nach;
	print();
    }
    static void turmversetzen(int n, String links, String mitte, String rechts)
    {
        if (n>0)
        {
            turmversetzen(n-1, links, rechts, mitte);
            ausgabe(n,links,rechts);
            turmversetzen(n-1, mitte, links, rechts);
	}
        else {
	    ausgabe(n,links,rechts);	    
	}
    }

    static void print(){
	for(String i: tuerme){
	    System.out.println(i);
	}
    }

    public static void main(String[] args){
	tuerme = new String[]{"links","links","links","links","links"};
	print();
	turmversetzen(tuerme.length -1, "links", "rechts", "mitte");	
    }

}```
Ich war mal so frei und habe ein paar kleine Änderungen vorgenommen, die dich evtl. weiterbringen.

Zuerst benötigst du eine Möglichkeit, den aktuellen Status festzuhalten. ein String[] tuerme ist hier z.B. eine ausreichende Datenstruktur.

Die Methode ausgabe ist die einzige in der wirklich ein Spielstein bewegt wird. Also sollte hier auch der Status geändert werden. Nach der Änderung lasse ich das aktuelle Spielfeld ausgeben.

Da beim Programmieren typischerweise mit 0 angefangen wird zu zählen, hab ich noch das if angepasst. 

Um jetzt eine Ausgabe hinzubekommen wie sie SlaterB vorgeschlagen hat, muß die print Methode entsprechend angepasst werden.

diese Datenstruktur + Modizifierung ist ja noch sehr human, etwa gegenüber Matrix im Link,

dafür beim Printen dann etwas mehr Aufwand herauszudröseln, was wo sitzt :wink:

Hier bitte-schön:

        if (args[0] > 0) {
            Integer i = Integer.valueOf(args[0] - 1);
            setze(i, args[1], args[3], args[2]);
            print(args[0], args[1], args[3]);
            setze(i, args[2], args[1], args[3]);
        } else {
            print(args[0], args[1], args[3]);
        }
    }

    public static void print(Integer... args) {
        System.out.printf("Scheibe %d von %d nach %d%n", args);
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws IOException, NoSuchAlgorithmException {
        setze(3, 7, 8, 9);
        System.out.println(Math.round(1.1254567 * 100) / 100.0);```

...und jetzt z.B. ArrayList<ArrayList<Integer>>, in der die Integers liegen.

(Code einfach kopiert, ich kann auch die Ausgabe nicht nachvollziehen, weil ich keine drei Scheiben habe)

[QUOTE=SlaterB]diese Datenstruktur + Modizifierung ist ja noch sehr human, etwa gegenüber Matrix im Link,

dafür beim Printen dann etwas mehr Aufwand herauszudröseln, was wo sitzt ;)[/QUOTE]

SoC.

Aber die printMethode sieht dann doch schon etwas komplizierter aus.

	String result = new String();
	for(int i = 0; i<tuerme.length; i++){
	    int j = getNth(i, "links");
	    int k = getNth(i, "mitte");
	    int l = getNth(i, "rechts");
	    String a = println(j);
	    String b = println(k);
	    String c = println(l);
	    result = String.format("%s	%s	%s%n",a,b,c) + result;
	}
	System.out.println(result);
    }
    
    static String println(int i) {
	int n = i+1;
	String s = new String();
	s = s+ p(tuerme.length-n, " ");
	s = s+ p(n, "#");
	s = s+ p(1, "|");
	s = s+ p(n, "#");
	s = s+ p(tuerme.length-n, " ");
	return s;
    }

    static String p(int n, String st) {
	String s = new String();
	for (int k = 0; k < n; k++) {
	    s =s+st;
	}
	return s;
    }

    static int getNth(int i, String search){
	int count = -1;
	for(int j = tuerme.length-1 ; j>=0; j--) {
	    if(tuerme[j].equals(search)) {
		count++;
		if(i == count) {
		    return j;
		}
	    }
	}
	return -1;
    }```

um im Senf-Kommentarmodus zu bleiben:
new String() ? das muss doch nicht sein, „“ reicht,

das Array tuerme hieße wohl besser scheiben,
analog turmversetzen() scheibenversetzen(), Max1992 ist da mit seiner Vorlage Schuldiger

aber schön schön


   @CyborgBeta 

ist ja nicht dein Code, wenn ich das richtig lese,
allgemein angemerkt: in Methoden wie

    public static void setze(Integer... args) {
        if (args[0] > 0) {
            Integer i = Integer.valueOf(args[0] - 1);
            setze(i, args[1], args[3], args[2]);
            print(args[0], args[1], args[3]);
            setze(i, args[2], args[1], args[3]);
        } else {
            print(args[0], args[1], args[3]);
        }
    }

hilft ein Parametername ‚a‘ mehr als ‚args‘ :wink:

wobei, wofür ist hier überhaupt das Array, hat doch keine Bedeutung, kein längerfristiger Speicher,
es gibt auch nicht variabel viele Argumente für die Methode, mehr als drei haben keine Funktion

warum nicht Code mit Einzelvariablen, gleich sprechend, also

public class Test {
    public static void setze(int i, int von, int ueber, int nach)  {
        if (i > 0)  {
            setze(i - 1, von, nach, ueber);
            print(i, von, nach);
            setze(i - 1, ueber, von, nach);
        }  else  {
            print(i, von, nach);
        }
    }

    public static void print(int i, int von, int nach)  {
        System.out.printf("Scheibe %d von %d nach %d%n", i, von, nach);
    }

    public static void main(String[] args)  {
        setze(3, 7, 8, 9);
    }
}

?

zum Code von #1 ist das nun nur noch String statt int, keine echte Verbesserung


zu #1 kann ich dann wiederum meckern dass die Variablennamen ‚links, mitte, rechts‘ ungünstig sind,
der String-Inhalt „links“, „mitte“, „rechts“ kann sich darauf beliebig verteilen,
‚von, ueber, nach‘ passt besser, in der ausgabe()-Methode zwei davon ja auch schon genommen

Denkbar wäre auch Object… oder Objekt[], es ging mir einfach darum, printf anständig aufrufen zu können. Will man für jeden Stab z. B. die Scheiben f, d, und a speichern (a liegt obenauf), kommt man um eine Datenstruktur wie Array, Feld, Liste usw. nicht umhin - oder?

@SlaterB , args klingt knackig. :wink:

gewiss braucht man eine Datenstruktur, wie das tuerme-Array in #8 welches besser ein scheiben-Array wäre,

aber einfach irgendwo irgendein Array einführen hilft nicht weiter,
die 4 Parameter sind für sich gut, sie als Parameter zum Array zu machen bewirkt gar nichts, falls das noch im Zusammenhang stand

Du könntest mir mal sagen, ob da jedes Mal eine neues Array erstellt wird… (du bist whrs. einer der wenigen, der das weiß)

So

        if (i > 0) {
            int i2 = i - 1;
            setze(i2, j, l, k);
            print(i, j, l);
            setze(i2, k, j, l);
        } else {
            print(i, j, l);
        }
    }

    public static void print(Object... args) {
        System.out.printf("Scheibe %d von %d nach %d%n", args);
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws IOException, NoSuchAlgorithmException {
        setze(3, 7, 8, 9);```

oder so (in schön)

```    public static void setze(int i, int j, int k, int l) {
        if (i > 0) {
            int i2 = i - 1;
            setze(i2, j, l, k);
            print(i, j, l);
            setze(i2, k, j, l);
        } else {
            print(i, j, l);
        }
    }

    public static void print(int i, int j, int k) {
        staebe[k].add(staebe[j].remove(staebe[j].size() - 1));
        for (int l = 0; l < 3; l++) {
            int idx = 2 - l;
            for (ArrayList<Integer> arrayList : staebe) {
                System.out.printf("% 3d", idx < arrayList.size()
                        ? arrayList.get(idx) : 0);
            }
            System.out.println("");
        }
        System.out.println("");
    }
    private static final ArrayList<Integer>[] staebe = new ArrayList[3];

    static {
        for (int i = 0; i < staebe.length; i++) {
            staebe** = new ArrayList<Integer>();
            staebe[0].add(3 - i);
        }
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws IOException, NoSuchAlgorithmException {
        setze(2, 0, 1, 2);```

Sag t jetzt nicht, das wäre stümperhaft.


Ausgabe in Schön:
[spoiler]

run:
0 0 0
2 0 0
3 0 1

0 0 0
0 0 0
3 2 1

0 0 0
0 1 0
3 2 0

0 0 0
0 1 0
0 2 3

0 0 0
0 0 0
1 2 3

0 0 0
0 0 2
1 0 3

0 0 1
0 0 2
0 0 3

1.13
Bitte a|b|cLeerzeichenProdukt eintippen:

[/spoiler]


Jetzt kann man sich auch ohne Münzen e was darunter vorstellen.

Edit: Dieses `throws IOException, NoSuchAlgorithmException` ist noch ein Relikt/Über*bleib*sel aaaus lääängst vergaaangenen Zeiten, hihi.

bei print(Object… args) wird jedenfalls ein Array erstellt wenn Einzelobjekte übergeben werde,