Programmierübungen

Im Folgenden finden sich abwechselnd ein kurzer Einleitungstext gefolgt von einer oder mehreren dazugehörigen Aufgaben. Fällt Dir die erste Aufgabe zu einem Thema sehr leicht, so kannst Du die weiteren ruhig überspringen. Fällt Dir die Aufgabe hingegen schwer, so empfiehlt es sich, auch die weiteren noch zu bearbeiten.
Diese Seite werde ich einige Zeit im Netz stehen lassen, Du kannst also immer nachsehen, bzw. Aufgaben üben. Möglicherweise werde ich noch einige Musterlösungen anbieten, dies ist allerdings nicht sicher.
Viel Spaß damit!

  1. Tippen, Speichern und Ausführen
  2. Die Variablentyperweiterung ,Array'
  3. Ein Wort zu Methoden
  4. Übergabe von Werten beim Programmstart
  5. For-Schleifen
  6. While-Schleifen
  7. If-Selektion
  8. Spaß mit Objekten
  9. Noch mehr Spaß mit Objekten
  10. Die Herausforderung

Tippen, Speichern und Ausführen

So geht's:

  1. Starte den Emacs, den XEmacs oder einen anderen Editor
  2. Öffne eine Datei, die [Klassenname].java heißt. Achtung: Auf die Groß- Kleinschreibung achten!
  3. Tippe Dein Programm.
  4. Speichere es ab.
  5. Öffne ein XTerm-Fenster
  6. Gib den Befehl setup java ein, so er noch nicht in Deiner .login-Datei steht.
  7. Gib den Befehl javac [Dateiname] ein - das kann etwas dauern.
  8. Führe das Programm mit dem Befehl java [Dateiname] ([Argumente]) aus. Die Argumente können auch entfallen.

Zum Inhalt

Probier's:

  1. Tippe das folgende Programm ab, kompiliere es (javac) und führe es aus.
    public class HelloWorld {
    public static void main(String args[]) { System.out.println("Hello World!"); }

    }

  2. Erstelle ein Programm, das die Mitteilung ,Hello World!' in einen Kasten aus Sternen setzt: ****************
    * Hello World! *
    ****************

Zum Inhalt


Arrays

Was ist das?

Ein Array ist eine Erweiterung eines Variablentyps, und zwar werden mehrere Variablen des gleichen Typs unter einem Namen zusammengefaßt. Um die einzelnen Variablen unterscheiden zu können, werden sie mit einem Index versehen, der von 0 bis (Größe des Arrays)-1 geht. Der Index steht in eckigen Klammern.
OK, ein Beispiel: String args[] ist ein Array von Strings, das ,args' heißt. Will man auf das 3. Element von args[] zugreifen, so schreibt man: args[2]. Diese Verbindung von Variablenname und Arrayindex kann wie ein neuer Variablenname benutzt werden.
Der Nutzen liegt darin, daß man nun über eine Variable auf eine Variable zugreifen kann. Nehmen wir an, in der int-Variable nr sei abgespeichert, auf welchen Datensatz man zugreifen möchte. Dann kann dieser Datensatz direkt z.B. vermittels System.out.println(name[nr]); ausgegeben werden. Natürlich kann man name[nr] auch in anderen Befehlen benutzen, wie einen ,normalen' Variablennamen auch.

Zum Inhalt

So geht's:

Um ein Array einzurichten, benutzt man folgenden Programmcode:

Variablentyp Variablenname Instantiierung
String Namen[] = new String[100];
int Matrnr[] = new int[100];
int fib[] = {0, 1, 1, 2, 3, 5, 8};
Boolean flags[];    

In Zeile 1 und 2 werden Arrays fester Größe eingerichtet. Auf die einzelnen Elemente kann in der Folge mit Namen[nr] bzw. mit Matrnr[nr] zugreifen, wobei der Wert von nr von 0 bis 99 reichen darf.
In Zeile 3 werden gleichzeitig die einzelnen Elemente des Arrays instantiiert: fib[4] hat z.B. den Wert 3. Die Größe dieses Arrays ist auch festgelegt, sie reicht von 0 bis 6.
In der letzten Zeile wird ein Array definiert, aber noch nicht instantiiert. Bevor man das Array benutzt, muß man dieses nachholen. Diese Möglichkeit benutzt man, falls man die Größe des Arrays erst später festlegen möchte.

Zum Inhalt

Probier's:

Sorry, aber die sinnvolle Benutzung von Arrays setzt die Kenntnis von Schleifen voraus. Übungen folgen also erst später...

Zum Inhalt


Ein Wort zu Methoden

Was ist das?

Methoden sind Unterprogramme: Häufig benutzte Befehlsfolgen werden zusammengefaßt und mit einem Namen versehen. Wenn nun - wie ein neuer Befehl - dieser Name benutzt wird, wird die Methode aufgerufen, also die dort stehende Befehlsfolge abgearbeitet. Am Ende der Methode oder aber nach Ausführung des return-Befehls kehrt das Programm direkt an die Stelle nach dem Methodenaufruf zurück.
Eine Methode hast Du schon kennengelernt: Die main-Methode. Diese wird nicht von Dir aufgerufen, sondern ist die Methode, die beim Starten des Programms aufgerufen wird.
Um Methoden flexibel zu halten, kann man ihr Parameter übergeben. Das bedeutet, daß der Methode Variablen zur Verfügung stehen, deren Werte beim Aufruf der Methode angegeben werden.

Zum Inhalt

So geht's:

Sieh Dir noch einmal das Beispiel der main-Methode an:

public static void main(String args[]) {

[Befehlsfolge]
}

Was bedeutet public? Das bedeutet, daß diese Methode überall sichtbar ist, d.h. sie kann von jeder anderen Klasse oder Programm aufgerufen werden. Weiterhin gibt es noch ,private' (nur von der eigenen Klasse aus aufrufbar) und ,protected' (nur von der eigenen und abgeleiteten Klassen aus aufrufbar).
Was bedeutet static? Das heißt, daß die Variablen dieser Methode einmal beim ersten Aufruf angelegt werden, jeder weitere Aufruf greift dann auf die gleichen Variablenwerte zu. Das Gegenstück ist ,dynamic'; dies ist dann die Standarteinstellung, die nicht explizit angegeben werden muß.
Was bedeutet void? Das bedeutet, daß diese Methode keinen Wert zurückliefert. Eine Methode kann auch wie eine (mathematische) Funktion benutzt werden, die dann einen Wert zurückliefert. Im Programm kann eine solche Methode dann wie eine Variable vom Typ des Rücklieferungswerts benutzt werden (abgesehen von einer Wertzuweisung, die an eine Funktion natürlich nicht möglich ist). Will man eine solche Funktion erstellen, so gibt man anstatt von ,void' den Typ der Methode an; In der Methode folgt dann irgendwann der Befehl return. Der Wert/die Variable, die hinter return steht, wird zurückgeliefert.
public int foo() ist z.B. eine öffentliche, nicht-statische Funktion namens ,foo', die einen Wert vom Typ ,int' zurückliefert.
Nun folgt der Name der Methode (der üblicherweise klein geschrieben wird). Dann folgt entweder ein leeres Klammerpaar (s. foo) oder eine Klammer, in der die Argumente aufgelistet sind (s. main). Die einzelnen Variablen werden mit Typ angegeben und durch Kommata getrennt. main wird z.B. ein Array von Strings übergeben, das ,args' heißt. Es werden dabei nicht die Variablen übergeben, sondern neue Variablen angelegt, und selbige dann mit dem Übergabewert instantiiert.
Schließlich folgen die Befehle der Methode, eingefaß von geschweiften Klammern.

Zum Inhalt

Probier's:

Für diese Übungen ist die Kenntnis des nächsten Abschnitts wichtig, sie folgen nach den Übungen des folgenden Kapitels.

Zum Inhalt


Übernehmen von Argumenten aus der Befehlszeile

Was ist das?

Argumente sind zusätzliche Informationen, die der Ausführende eines Programmes angeben kann. Sie folgen nach dem Programmaufruf aus dem XTerm, getrennt durch Leerzeichen:
java [Dateiname] [1. Argument] [2. Argument]...

Zum Inhalt

So geht's:

main ist auch eine Methode, d.h. man kann ihr auch Argumente übergeben. Diese sind ein Array von Strings. Üblicherweise nennt man dieses Array ,args', aber auch jeder andere Name ist natürlich zulässig. Die Übergabe der Argumente findet sich in der runden Klammer nach dem Methodennamen ,main' (siehe auch das Programmgerüst zum Abtippen)
Dabei steht das erste übergebene Argument in args[0], das zweite in args[1], usw.
Will man andere Typen als einen String als Argument erhalten, so muß man zunächst die Argumente als String einlesen, und anschließend in den gewünschten Typ konvertierten. Beispiel:
int i=Integer.parseInt(args[0]);
initialisiert eine int-Variable i und weist ihr den int-Wert des 1. Arguments zu.

Zum Inhalt

Probier's:

  1. Implementiere ein Programm ,Tier.java', das auf den Aufruf ,java Tier Kamel' ,Kamel ist ein Tier' ausgibt.
  2. Implementiere ein Programm ,Add.java', das auf den Aufruf ,java Add [x1] [x2]' die Summe aus x1 und x2 ausgibt. D.h., Du mußt also zunächst beide Werte in ints konvertieren, dann addieren und letztendlich ausgeben.

  3. Jetzt folgen die Aufgaben zu den Methoden!
  4. Schreibe das ,Add'-Programm so um, daß es eine Methode namens ,plus' benutzt, die die Addition ausführt. plus soll public sein, und einen Wert vom Typ int zurückliefern. Als Argumente werden ebenfalls zwei ints übergeben.
  5. Schreibe ein Programm namens ,Fib', dem als Parameter eine int übergeben wird, und das die [Parameter]ste Fibonaccizahl berechnet.
    Benutze dabei die rekursive Definition ( F(0)=0; F(1)=1; F(n)=F(n-1)+F(n-2) ), benutze rekursive Aufrufe, d.h., daß sich Deine Methode selbst aufrufen soll.
    Merke: Hier kommt es nicht auf eine effiziente Implementierung an!

Zum Inhalt


For-Schleifen

Was ist das?

Schleifen sind Programmkonstrukte, die Wiederholungen (Iteration) möglich machen. Eines der einfachsten Beispiele ist die For-Schleife. Sie benutzt eine Zählvariable, eine Inkrementfolge und eine Abbruchbedingung. Normalerweise nutzt man eine int, die bei jedem Schleifendurchlauf um 1 erhöht wird und als bricht bei Erreichen eines bestimmten Wertes ab: Damit kann man eine n-fache Ausführung einer Befehlfolge erreichen.

Zum Inhalt

So geht's:

for (int i=0; i<n; i=i+1) { [Befehlsfolge] }
for
ist der Befehl, in der Klammer wird eine neue int Variable erzeugt und mit 0 instantiiert. Damit ist die Zählvariable festgelegt. Mit i=i+1 oder i++ wird die Inkrementsfolge festgelegt: Bei jedem Schleifendurchlauf wird i um eins erhöht. Schließlich folgt noch eine Abbruchbedingung: Sobald i=n (das ist eine andere intVariable, die vorher festgelegt worden sein muß, man kann natürlich auch eine feste Zahl angeben), wird die Schleife nicht mehr ausgeführt.
Hinweis: Obwohl man meist ints als Zählvariablen benutzt, gibt es auch durchaus Fälle, in denen ganz andere Konstrukte benutzt werden, wie z.B. enumerations.

Zum Inhalt

Probier's:

  1. Implementiere ein Programm, das die Zahlen von 0 bis n auf dem Bildschirm ausgibt, wobei n dem ersten Parameter entspricht.
  2. Erweitere dieses Programm derart, daß es vom ersten zum zweiten Parameter zählt.
  3. Implementiere ein Programm namens ,Kasten', das ein Quadrat aus Sternen (s. Tippen, Aufgabe 2) malt. Die Größe des Quadrats soll als Parameter übergeben werden können.
  4. Implementiere eine effiziente Version von ,Fib', die von 0 bis n zählt und dabei den Wert von F(i), F(i-1) und F(i-2) jeweils neu berechnet. n soll dabei als Parameter dem Programm übergeben werden.

Zum Inhalt


While-Schleife

Was ist das?

Die While-Schleife verfügt im Gegensatz zur For-Schleife nur über eine Abbruchbedingung. Ob und wann diese erzeugt wird, hängt von den Befehlen der Schleife ab.

Zum Inhalt

So geht's:

while ( [Bedingung] ) { [Befehlsfolge] }
while
ist der Befehl. Die Bedingung ist ein Ausdruck, dem ein Boolscher Wert zugeordnet werden kann, also z.B. eine Variable vom Typ Boolean, oder ein Vergleich (n==o, 7<m, p!=q), oder ähnliches.
In dieser Bedingung können auch logische Verknüpfungen benutzt werden:

Operator Bedeutung
! Negation
&& UND-Verknüpfung
|| ODER-Verknüpfung

Die Schleife wird so lange ausgeführt, bis die Bedingung nicht mehr gilt (den Wert false annimmt).
Gilt die Bedingung vor Ausführung der While-Schleife noch nicht, so wird diese vollständig übersprungen. Mit dem Befehl do { [Befehlsfolge] } while ( [Bedingung] ); kann man ein einmaliges Durchlaufen der Schleife erzwingen.

Zum Inhalt

Probier's:

  1. Schreibe das Programm, das vom ersten Eingabeargument zum zweiten zählt, mit Hilfe einer Whileschleife
  2. Noch einmal Fibonacci: Das Programm soll die nächstkleinere Fibonaccizahl zum ersten Parameter ausgeben, ist der Parameter also z.B. im Bereich von 5 bis 7, so soll 5 ausgegeben werden, im Bereich von 8 bis 12 8, usw.
  3. Implementiere ein Programm, das die Zahl n ausgibt, so daß gilt, das die Summe der Zahlen von 1 bis n gerade noch kleiner als der Übergabeparameter ist.

Zum Inhalt


Die If-Selektion

Was ist das?

Die If-Selektion entspricht so ungefähr der Selektion bei Registermaschinen-Programmen. Es gibt eine Bedingung, und falls diese wahr (true) ist, so wird das eine Programm ausgeführt, falls sie unwahr (false) ist, wird ein anderes Programm ausgeführt. Nach der Selektion kann das Programm linear fortgeführt werden.
Allerdings ist die Bedingung nicht nur, ob eine Variable den Wert 0 hat, sondern eine ebenso allgemeine Bedingung wie bei der While-Schleife.

Zum Inhalt

So geht's:

if ( [Bedingung] ) { [Befehlsfolge 1] } else { [Befehlsfolge 2] }
if und else sind die Befehle, die Bedingung ist ein Konstrukt, dem sich ein boolscher Werte (true/false) zuordnen läßt (s. While-Schleife).
Die Befehlsfolge 1 wird ausgeführt, wenn die Bedingung wahr ist, die Befehlsfolge 2 in jedem anderen Fall. Die else-Klausel ist nicht notwendig.

Zum Inhalt

Probier's:

  1. Implementiere ein Programm, das ausgibt, ob das 1. Argument gerade oder ungerade ist.
  2. Implementiere ein Programm, das nur Dich begrüßt, d.h. es soll "Hallo [Name]" ausgeben, falls das 1. Argument Deinem Namen entspricht, in jedem anderen Fall soll nichts ausgegeben werden.
  3. Erweitere das Programm aus Aufgabe 1, so daß der Reihe nach für jedes Argument ausgegeben wird, ob es gerade oder ungerade ist. Benutzte eine Schleife und die Funktion args.length(), die angibt, wie groß ein Array ist.

Zum Inhalt


Spaß mit Objekten

Was ist das?

Ich gebe zu: Die Überschrift ist irreführend. Zumindest anfangs machen Objekte alles andere als Spaß...
Du hast schon oft Variablen benutzt. Diese hatten dann einen bestimmten Typ z.B. int, und Du konntest bestimmte Operationen mit ihnen ausführen, z.B. die Addition.
Objekte sind nun - im weitesten Sinne - selbst definierte Variablen. Das ist nicht so schlimm wie es klingt: Im Prinzip stellst Du nur die bereits bekannten Variablentypen zusammen. Z.B. läßt sich der Variablentyp "Schachbrett" als 64 Integer-Werte darstellen, wobei eine 0 freies Feld bedeutet, eine 1 weißer Bauer, eine -1 schwarzer Bauer, usw.
Zudem stellst Du bestimmte Methoden zur Verfügung, die für Instanzen dieses Objektes genutzt werden könen. Auf Schachbrett wäre z.B. eine ,ziehe Figur'-Methode sinnvoll.

Zum Inhalt

So geht's:

Die Klasse

Jedes Objekt ist eine eigene Klasse. Willst Du also ein neues Objekt entwerfen, so fängst Du mit
class [Klassenname] {
an. Beachte: Diese Klasse ist nicht public, nur eigenständige Programme sind public. Klassennamen werden üblicherweise groß geschrieben (z.B. Schachbrett, Tupel,...) Methoden hingegen klein (z.B. addiere, zaehleHinzu,...). Dies ist eine Konvention, aber nicht notwendig. Trotzdem empfehle ich, daß man sich an diese Regeln hält.

Ein Beispiel für ein Objekt

Die Variablen

Nach dem Titel der Klasse werden die Klassenvariablen definiert. Dies sind die Variablen, die in der ganzen Klasse verfügbar sein sollen. Diese Variablen können public, private oder protected sein (siehe dazu Methoden).

Ein Beispiel für ein Objekt

Der Konstruktor

Der Konstruktor wird aufgerufen, wenn eine Instanz der Klasse gebildet werden soll. Er trägt immer den gleichen Namen wie die Klasse (auch Groß-/Kleinschreibung) und ist public.
Wenn man ein Objekt benutzen will, so wird dieser Konstruktor aufgerufen, und es werden ihm in der Regel auch die Werte übergeben, mit denen die Klassenvariablen instantiiert werden.

Ein Beispiel für ein Objekt

Methoden einer Klasse

Ein Objekt bzw. Klasse verfügt natürlich auch über Methoden. Mit diesen können Aktionen ausgeführt werden oder die Variablenwerte verändert.
Die Programmierung solcher Methoden ist identisch zur Implementierung von Methoden in einem Programm bzw. einer öffentlichen Klasse.

Ein Beispiel für ein Objekt

Beispiel für ein Objekt

class Tupel { // Klassenname

private int first; // 1. Klassenvariable
private int second; // 2. Klassenvariable

public Tupel() { // 1. Konstruktor first=0;
second=0;
}

public Tupel(int f, int s) { // 2. Konstruktor first=f;
second=s;
}

public int getFirst() { // Eine Methode return first; }

public void setSecond(int s) { // Noch eine Methode second=s; }

public void makeZero() {Weil Methoden so schön sind... first=0;
second=0;
}
} // Ende der Klasse Tupel

Zum Inhalt

Probier's:

  1. Tippe die Beispielklasse ab und kompiliere sie. Du erhälst eine Datei namens Tupel.class, die nicht ausführbar ist.
  2. Erweitere die Klasse um einen Konstruktor, der nur einen int-Wert übergeben bekommt und first und second mit diesem Wert instantiiert.
  3. Implementiere die Methoden getSecond() und setFirst(int f).
  4. Implementiere eine toString() Methode, die folgenden String zurückliefert: "([first]/[second])"
    Anmerkung: Diese Methode wird von dem Befehl System.out.print() automatisch aufgerufen, falls im Argument eine Variable vom Typ Tupel vorkommt.
  5. Implementiere eine equal(Tupel t)-Methode, die true zurückgibt, falls das Tupel t mit dem aktuellen Tupel übereinstimmt, d.h. wenn sowohl first- als auch second-Werte identisch sind, und false sonst.

Zum Inhalt


Wie benutzt man Objekte?

So geht's:

Tupel t = new Tupel(3,5);
Diese Zeile erstellt eine Variable namens t vom Typ Tupel, und instantiiert selbige mit den Werten 3 und 5. Dieses Instantiieren entspricht dem Aufruf des Konstruktors.
Um eine Methode für ein Objekt aufzurufen, tippt man zunächst den Namen des Objekts (oder der Klasse, falls auf kein spezielles Objekt zugegriffen werden soll), dann direkt einen Punkt, dann den Namen der Methode und schließlich die Klammer mit den Argumenten, bzw. eine leere Klammer.
Beispiel:

t.setFirst(3);
int x=t.getSecond();
t.setZero();
Man kann auch auf Variablen des Objekts direkt zugreifen, falls diese public sind. Dieser Zugriff ist identisch zu dem Aufruf einer Methode, nur entfallen die Klammern. Man kann den Objektvariablen auf diese Art auch Werte zuweisen. Die folgenden Beispiele funktionieren nicht mit der Tupelklasse des Beispiels, da first und second beide private sind.
Beispiel: int z=t.first;
t.second=7;
Auf statische Variablen kann man auch direkt durch Angabe des Klassenanmens zugreifen. Im Beispiel des Schachbrettes kann es z. B. sein, daß der Nutzer der Klasse die Verschlüsselung der Figuren nicht kennen soll/will. Dann kann man am Anfang der Klasse (bei der Definition der Klassenvariablen) diese Werte codieren:
final static int LEER=0;
final static int WHITE_PAWN=1;
final static int BLACK_PAWN=-1;

usw. Auf diese Werte wird dann mit dem Befehl Schachbrett.WHITE_PAWN zugegriffen. Noch einmal ein komplexer Beispielaufruf:
my_board.setFigure(new Place("h", 8),Schachbrett.BLACK_TOWER);
my_board ist eine Variable vom Typ Schachbrett. Für diese wird die Methode setFigure aufgerufen. Diese Methode erwartet zwei Argumente: Eins vom Typ Place (ähnlich dem Tupel) und eins vom Typ int. Das erste wird gleich ganz neu entworfen, und direkt nach dem Aufruf wieder verworfen. Das zweite entspricht dem int-Wert, der in der Klasse Schachbrett der final static Variablen BLACK_TOWER zugewiesen wurde.
Klingt kompliziert, aber ist einfach, wenn man es ein paar mal gemacht hat...

Zum Inhalt

Probier's:

  1. Entwirf eine Klasse TestTupel, in der eine Variable vom Typ Tupel entworfen wird (ohne Wertübergabe) und anschließend auf dem Bildschirm ausgegeben.
  2. Es sollen die ersten beiden Argumente, die beim Aufruf von TestTupel übergeben werden, an die Variable vom Typ Tupel übergeben werden.
  3. Es soll ausgegeben werden, ob die first und second Werte des so instantiierten Tupels gleich sind.
  4. Es soll verglichen werden, ob das Tupel aus den ersten zwei Argumenten gleich dem Tupel aus Argument 3 und 4 ist.

Zum Inhalt


Die Herausforderung: Das Springer Problem

Probier's:

Das Springer Problem

Auf einem Schachbrett soll ein Springer von einem der Eckfelder aus jedes andere Feld genau einmal besuchen. Der Springer zieht ein Feld in eine Richtung, dann dreht er sich um 90 Grad und zieht zwei Felder weit, oder aber er zieht zwei Felder in eine Richtung und dann ein weiteres in 90 Grad Richtung. Das ziehen erfolgt dabei immer gerade, nie diagonal.

Wie funktioniert's?

Zur Lösung dieses Problems kann man Backtracking benutzen. Das bedeutet, daß man der Reihe nach jedes noch nicht besuchte, vom Springer erreichbare Feld aufsucht, und von dort aus fortsetzt. Findet man kein freies erreichbares Feld mehr, so nimmt man den letzten Zug zurück und versucht von dieser letzten Position aus die nächste Möglichkeit.
Probiere, ob Du es mit diesen Informationen schon schaffst, falls nicht, folgen hier noch weiter Informationen:
Zunächst die Klassenübersicht. Hier siehst Du, welche Klasseneinteilung sich anbietet.
Danach folgen eine genauere Erläuterung, was diese Klassen zur Verfügung stellen sollen.
Schließlich folgt noch eine Liste von Tipps, wie der Algorithmus implementiert werden kann. Es gibt natürlich auch andere Lösungswege.
Für diejenigen, die völlig verzweifelt sind, folgt noch eine Musterlösung.

Die Klassenübersicht

  1. Das Schachbrett
  2. Die Plätze
  3. Die Lösungsklasse

Das Schachbrett

Diese Klasse entspricht hauptsächlich einem zweidimensionalen Array vom Typ Boolean. Zweidimensional bedeutet, daß es zwei Indizes gibt, statt einer eckigen Klammer gibt es zwei. Man kann durch Angabe von zwei Werten (waagrecht und senkrecht) auf dieses Array zugreifen.
Ist der Boolean-Wert false, so wurde das Feld bereits besucht (ist verboten), ist er true, so ist das Feld noch unbesucht, kann also noch betreten werden.

Die Plätze

Die Platz-Klasse stellt eine waagrechte und eine senkrechte Koordinate zusammen. In dieser Klasse sollte u.a. auch eine toString-Methode zur Verfügung gestellt werden.

Die Lösungsklasse

Die Lösungsklasse verfügt über ein Schachbrett und ein Array vom Typ Platz. In diesem Array sollen der Reihe nach die besuchten Felder abgespeichert werden. Zudem ist die Lösungsklasse public und besitzt eine Main-Methode. Das erste Übergabeargument dieser Klasse soll die Größe des Brettes festlegen.

Ein paar Tipps:

Diese Tipps helfen, falls der Lösungsansatz oben nicht reicht, aber versuch es erst einmal ohne!

  1. Don't panic!
  2. Benutze eine counter-Variable, die angibt, welcher Zug gerade bearbeitet wird.
  3. Benutze eine Methode, die den Counter als Argument hat. Diese Methode ruft sich selbst rekursiv auf.
  4. Der Springer hat acht mögliche Zielfelder. Speichere diese Zielfelder in einem Array ab (in welche Klasse paßt die Methode, die die Zielfelder berechnet, am besten?) und teste die Zielfelder mit einer For-Schleife.
  5. Die rekursiven Aufrufe erfolgen aus der For-Schleife heraus. Ist die For-Schleife beendet, dann wurde wohl keine Lösung von diesem Feld aus gefunden. Der Zug wird durch das Ende der Methode automatisch zurückgenommen. Du mußt nur noch das Feld dieses Zuges wieder befreien, da der Springer es nach Rücknahme des Zuges noch nicht benutzt hat.

Musterlösung, nur für Warmduscher

Die Musterlösung zählt auch die Anzahl der gefundenen Lösungen und die Anzahl der Hamiltonzyklen (der Springer könnte nach dem Besuch aller Felder direkt auf das Startfeld springen).

Impressum