3.7 Strukturiertes Speichern mit Arrays
Bei dem Projekt „Landschaft“ stößt man mit den bisher bekannten Mitteln schnell an Grenzen: Die Erstellung von komplexen Strukturen ist sehr aufwendig: Möchte man einen Zaun oder Sonnenstrahlen hinzufügen, werden viele gleichartige Objekte gebraucht. An dieser Stelle ist die Nutzung von Arrays und Zählschleifen vorteilhaft.
Mit einem Array kann man mehrere Objekte vom gleichen Typ verwalten. Die Objekte sind indiziert, d.h. man kann über einen Index auf die einzelnen Elemente zugreifen. Das erste Feld hat dabei den Index [0], das letzte Feld eines Arrays mit 10 Objekten hat den Index [9]. Man sagt auch: Der Index basiert auf 0.
Die Arbeit mit Arrays soll im Folgenden am Beispiel des Zauns erklärt werden.
Aufgabe: Zaun erstellen
Im Prototypen ist eine Landschaft, in die der Zaun hinzugefügt werden soll. Die folgenden Schritte beschreiben das Vorgehen. Übernehme jeweils den Quelltext in das Projekt. Wichtig: Du darfst den Quelltext nicht einfach kopieren! Da der Syntax für Arrays ungewöhnlich ist und von den bisher behandelten Elementen stark abweicht, ist das Abtippen nötig!

Deklaration und Initialisierung eines Arrays
Ein Zaun besteht aus Zaunpfählen und Zaunstreben. Es handelt sich um Objekte der Klasse SGRechteck
. Dies wird bei der Deklaration festgelegt. Durch eckige Klammern hinter dem Typ wird festgelegt, dass es sich nicht um ein einzelnes Objekt handelt, sondern um ein Array von Objekten (Zeile 5-6).
Im Konstruktor erfolgt dann die Erzeugung des Arrays. Hier muss festgelegt werden, wie viele Objekte in dem Array gespeichert werden können. Dies erfolgt mit dem new
-Operator. In den eckigen Klammern wird die Anzahl der Elemente in dem Array angegeben. Hier sollen in dem Array für zaunpfaehle zehn Objekte abgelegt werden können, in dem Arrays für die Zaunstreben nur zwei (Zeile 13 und 14).
Durch diese Anweisung wird allerdings ein leeres Array erzeugt! In den einzelnen Feldern finden sich noch keine Inhalte. Die Erzeugung der eigentlichen SGRechteck
-Objekte muss also im nächsten Schritt vorgenommen werden.
public class LandschaftMitZaun
{
private SGLeinwand meineLeinwand
...
private SGRechteck[] zaunpfaehle;
private SGRechteck[] zaunstreben;
public LandschaftMitZaun()
{
meineLeinwand = new SGLeinwand(500,500);
...
zaunpfaehle = new SGRechteck[10];
zaunstreben = new SGRechteck[2];
}
}
Befüllen des Arrays, Zugriff
Das leere Array soll nun befüllt werden. Um an eine bestimmte Position ein neues Objekt abzulegen, wird an den Bezeichner des Arrays der Index in eckigen Klammern angehängt. Nebenstehend wird dem ersten Feld des Arrays zaunstreben
(Index 0) ein neues SGRechteck
-Objekt zugewiesen.
Der Zugriff auf den Inhalt aus dem Array erfolgt nach dem gleichen Prinzip. In der zweiten Zeile wird auf das Objekt mit Index 0 zugegriffen und dessen Füllmuster geändert.
Bei den beiden Zaunstreben fällt auf, dass ihre Erzeugung sehr ähnlich ist. Nur bei der y-Koordinate gibt es einen Unterschied. Daher werden Arrays häufig über Zählschleifen befüllt, da dies viel Arbeit erspart.
zaunstreben[0] = new SGRechteck(210,383,90,3);
zaunstreben[0].setzeFuellung(true);
zaunstreben[0].setzeFarbe(0.4,0.2,0.1);
zaunstreben[1] = new SGRechteck(210,393,90,3);
zaunstreben[1].setzeFuellung(true);
zaunstreben[1].setzeFarbe(0.4,0.2,0.1);
Arrays durchlaufen mit Zählschleifen
Das Array zaunpfaehle
hat 10 Felder (mit den Indices 0 bis 9). Um alle Felder anzusprechen, benötigt man eine Zählvariable mit dem Anfangswert 0. Die Schleifenbedingung i < 10
und das Hochzählen um 1 sorgen dafür, dass jedes Feld in dem Array angesprochen wird.
Zusätzlich kann die Zählvariable innerhalb des Schleifenrumpfes genutzt werden, um Eigenschaftswerte eines Objekts in Abhängigkeit von ihrer Position im Array festzulegen: Im Beispiel wird der erste Zaunpfahl an der x-Position 210+0*10 erzeugt, der zweite an der x-Position 210+1*10, der dritte bei 210+2*10 usw. Jeder folgende Zaunpfahl steht also 10 Pixel weiter rechts als sein vorheriger.
int i = 0;
while( i < 10 )
{
zaunpfaehle[i] =
new SGRechteck(210+i*10, 380, 3, 20);
zaunpfaehle[i].setzeFuellung(true);
zaunpfaehle[i].setzeFarbe(0.4,0.2,0.1);
i++;
}
Die For-Schleife
Eine Zählschleife kann nicht nur mit einer while
-Schleife erstellt werden. Eine kürzere Version für die Zählschleife ermöglicht die for
-Schleife. Sie wird mit dem Schlüsselwort for
eingeleitet. In runden Klammern folgen dann drei Befehle, die durch ein Semikolon getrennt werden:
- Zuerst wird der Bezeichner für die Zählvariable festgelegt und ihr Startwert angegeben (hier:
int i = 0
). - Dann folgt die Bedingung. Solange diese Bedingung erfüllt ist, wird der Anweisungsblock ausgeführt (hier:
i < 10
). - Die letzte Anweisung wird jedes Mal ausgeführt, wenn der Anweisungsblock durchlaufen wurde. In diesem Fall wird die Zählvariable mit
i++
um 1 erhöht.
Alternative zur while
-Schleife:
for(int i = 0; i < 10; i++)
{
zaunpfaehle[i] =
new SGRechteck(210+i*10, 380, 3, 20);
zaunpfaehle[i].setzeFuellung(true);
zaunpfaehle[i].setzeFarbe(0.4,0.2,0.1);
}
Aufgaben
1. Sonnenstrahlen und Sterne
Im Prototypen sind die Sonnenstrahlen noch nicht vorhanden. Ergänze die Sonnerstrahlen. Deklariere und initialisiere dafür ein Array von SGRechteck
-Objekten und nutze die dreheUmMittelpunkt
-Methode, um die Rechtecke sternförmig hinter der Sonne anzuordnen.
Erstelle zusätzlich eine Methode werdeNacht. In dieser Methode soll eine Vielzahl von Sternen (als kleine SGKreis-Objekte) dargestellt werden. Die Koordinaten sollen per Zufall im oberen Teil der Leinwand gesetzt werden.


2. Quelltext analysieren
Erläutere, welcher der folgenden Quelltext welches der nebenstehenden Muster ergibt.
Variante 1
rechtecke = new SGRechteck[20];
for(int i = 0; i < rechtecke.length; i++)
{
rechtecke[i] = new SGRechteck(0,0,50+10*i,100+20*i);
rechtecke[i].setzeFuellung(true);
rechtecke[i].setzeFarbe(Math.random(), Math.random(), Math.random());
}
Variante 2
rechtecke = new SGRechteck[20];
for(int i = 0; i < rechtecke.length; i++)
{
rechtecke[i] = new SGRechteck(250,250,50+5*i,50+5*i);
rechtecke[i].drehe(i*10);
rechtecke[i].setzeFuellung(true);
rechtecke[i].setzeFarbe(Math.random(), Math.random(), Math.random());
}
Variante 3
rechtecke = new SGRechteck[20];
for(int i = 0; i < rechtecke.length; i++)
{
rechtecke[i] = new SGRechteck(25*i,25*i,25,25);
rechtecke[i].setzeFuellung(true);
rechtecke[i].setzeFarbe(Math.random(), Math.random(), Math.random());
}



3. Farbverläufe
- Erstelle einen Farbverlauf wie im nebenstehenden Bild. Der Farbverlauf besteht aus einem Array mit 100 SGRechteck-Objekten. Sowohl die Position als auch die Farbe müssen bei der Erzeugung der Rechtecke in einer Schleife von der Zählvariablen abhängen. Die Farben müssen nicht die gleichen sein wie im nebenstehenden Bild.
- Erstelle den zweiten Farbverlauf ähnlich zum ersten. Hier ist auch die Höhe der einzelnen Rechtecke von der Position im Array abhängig. Die Hintergrundfarbe ist schwarz.


4. Muster
Erstelle die beiden nebenstehenden Muster.


5. Schraffierter Farbverlauf
In der Klasse SchraffierterFarbverlauf
findet sich ein Farbverlauf, wie er in den letzten Stunden programmiert wurde. Er soll so erweitert werden, dass er schraffiert ist. Dazu soll jedes zweite SGRechteck
-Objekt nicht mit der Farbe des Farbverlaufs, sondern mit einer grauen Farbe gefüllt werden
6. Lauflicht
In der Klasse Lauflicht
wurde die Methode schalteLicht
implementiert.
- Erläutere die Funktionsweise der Methode
schalteLicht
. - Das Aufrufen der Methode
schalteLicht
führt nach einem Durchlauf des Lichts zu einer Fehlermeldung (ArrayIndexOutOfBoundsException
). Der letzte gültige Index im Array ist der Index[9]
. Daher muss nach dem Erhöhen der Variableni
überprüft werden, ob sie den Wert10
beinhaltet. Ist dies der Fall, muss der Wert auf0
gesetzt werden.
7. Schachbrett
In der Klasse Schachbrett
wird ein zweidimensionales Array von SGRechteck
-Objekten verwendet, um ein Schachbrett zu erzeugen. Allerdings wird jedes Feld mit einer zufälligen Farbe erzeugt. Ändere die Farbgebung jeweils so, dass sich die folgenden Muster ergeben.
Zusatzaufgabe 1: Quadratischer Farbverlauf
In Aufgabe 7 hast du zweidimensionale Arrays kennengelernt. Nutze ein zweidimensionales Array, um einen quadratischen Farbverlauf wie nebenstehend abgebildet zu erstellen. Die Farben müssen nicht übereinstimmen.
Zusatzaufgabe 2: Muster
Die beiden nebenstehenden Muster sind etwas für Tüftler. Bei dem linken Muster benötigst du Drehungen und Verschiebungen in Drehrichtung. Bei der dem rechten Muster brauchst du ein wenig Mathematik.