Zweidimensionale Felder
Ein Spielbrett, eine Tabelle, ein Bild aus Bildpunkten – all das hat Zeilen und Spalten. Dafür braucht man ein Feld, dessen Elemente selbst wieder Felder sind.
Anlegen und zugreifen
| Schreibweise | Bedeutung |
|---|---|
int[][] gitter |
deklariert ein zweidimensionales Feld |
new int[3][4] |
legt 3 Zeilen mit je 4 Spalten an |
gitter[1][2] |
Zeile 1, Spalte 2 |
gitter.length |
Anzahl der Zeilen |
gitter[0].length |
Anzahl der Spalten in Zeile 0 |
Merke dir die Reihenfolge: zuerst die Zeile, dann die Spalte. Wer das vertauscht, bekommt entweder falsche Werte oder einen Laufzeitfehler.
Ein zweidimensionales Feld ist in Wirklichkeit ein Feld von Feldern. Deshalb ist gitter[1] selbst ein int[].
Ein Bild dazu:
gitter
┌───────────────────────┐
0 │ 5 │ 0 │ 0 │ 0 │ ← gitter[0] ist ein int[] der Länge 4
├───────────────────────┤
1 │ 0 │ 0 │ 7 │ 0 │
├───────────────────────┤
2 │ 0 │ 0 │ 0 │ 9 │
└───────────────────────┘
0 1 2 3
Direkt mit Werten anlegen
Der Zugriff brett[i][i] läuft über die Hauptdiagonale.
a) Wie kommst du an die Gegendiagonale – also 3, 5, 7?
b) Wie an eine ganze Spalte, etwa die mittlere?
Auflösung
a) brett[i][brett.length - 1 - i]. Läuft i von 0 bis 2, läuft der zweite Index von 2 bis 0.
b) Man hält den Spaltenindex fest und lässt den Zeilenindex laufen:
for (int zeile = 0; zeile < brett.length; zeile++) {
IO.println(brett[zeile][1]);
}
Es gibt keine Abkürzung dafür – Java kennt brett[1] als ganze Zeile, aber nichts Entsprechendes für Spalten.
Ein Spielbrett
Die Methode gewinner prüft in einer Schleife sowohl Zeilen als auch Spalten.
a) Erkläre, wie das funktioniert – wofür steht i in der einen und in der anderen Prüfung?
b) Warum steht überall zusätzlich die Bedingung mit dem Punkt?
c) Warum steht bei den Diagonalen pBrett[1][1] != '.' und nicht pBrett[0][0] != '.'?
Auflösung
a) Bei pBrett[i][0] ist i der Zeilenindex – die Prüfung läuft waagerecht. Bei pBrett[0][i] ist i der Spaltenindex – die Prüfung läuft senkrecht. Beide Male läuft dieselbe Zählvariable von 0 bis 2.
b) Ohne sie wären drei leere Felder ein Gewinn: '.' == '.' == '.' ist wahr. Man muss also ausschließen, dass das geprüfte Feld leer ist.
c) Beide Diagonalen laufen durch die Mitte. Ist die Mitte leer, kann keine Diagonale voll sein – ein Test statt zwei.
Aufgabe 1: Rechnen im Gitter
Ergänze die Methoden so, dass alle Tests grün werden.
Tipp 1: Die Grundschleife
for (int z = 0; z < pGitter.length; z++) {
for (int s = 0; s < pGitter[z].length; s++) {
// hier steht pGitter[z][s] zur Verfügung
}
}
Beachte pGitter[z].length statt pGitter[0].length – so funktioniert es auch, wenn die Zeilen unterschiedlich lang sind.
Tipp 2: transponiert
Das neue Gitter hat so viele Zeilen, wie das alte Spalten hat – und umgekehrt:
int[][] neu = new int[pGitter[0].length][pGitter.length];
Und beim Kopieren gilt neu[s][z] = pGitter[z][s]. Die beiden Indizes tauschen die Plätze.
Aufgabe 2: Ein Labyrinth
Ein Labyrinth lässt sich als zweidimensionales Feld von Zeichen darstellen: # ist eine Wand, . ist frei, S der Start und Z das Ziel.
Zeichne es mit Scratch for Java auf die Bühne.
a) Zeichne jede Zelle als Punkt: Wände dunkel, freie Felder hell, Start grün, Ziel rot.
b) Berechne die Bildschirmkoordinate aus Zeile und Spalte. Achte darauf, dass die y-Achse nach oben zeigt, die Zeilennummern aber nach unten wachsen.
Tipp: Die Umrechnung
Bei einer Zellgröße von 36 Pixeln und dem Plan in der Bühnenmitte:
int x = -130 + spalte * 36;
int y = 110 - zeile * 36;
Das Minus vor zeile ist der Kern: Zeile 0 soll oben liegen, y-Werte werden nach unten aber kleiner.
Zusatzaufgabe
Java erlaubt Felder mit unterschiedlich langen Zeilen:
int[][] dreieck = new int[4][];
dreieck[0] = new int[1];
dreieck[1] = new int[2];
dreieck[2] = new int[3];
dreieck[3] = new int[4];
a) Erzeuge damit das pascalsche Dreieck bis zur zehnten Zeile. Jeder Wert ist die Summe der beiden darüber; die Ränder sind 1.
b) Gib es zentriert aus.
c) Erkläre, warum in diesem Fall die Bedingung s < pGitter[z].length unverzichtbar ist und s < pGitter[0].length das Programm zum Absturz bringen würde.