Arrays in Processing
Am Ende des Kapitels solltest du
- wissen, was eine Array ist,
- wissen, wie man Arrays deklariert, erzeugt und initialisiert,
- in der Lage sein, Arrays mit Hilfe von Schleifen zu initialisieren bzw. damit Werte aus einem Array auszulesen,
- den Begriff der Referenz einer Variable im Zusammenhang mit Arrays verstehen,
- in der Lage sein, Arrays für die Lösung von graphischen Aufgaben zu nutzen,
- Arrays mit Objekten als Elementen erstellen und mit ihnen umgehen können.
Ein Array oder Feld ist ein Container, der dazu dient, mehrere Elemente (Komponenten) des gleichen Typs aufzunehmen. Dabei können die Variablen über einen gemeinsamen Namen angesprochen werden und unterscheiden sich lediglich durch einen Index. Man kann sich das Array als eine lange Reihe gleichartiger Schubladen vorstellen, die durchnummeriert sind und deren Nummerierung mit 0 beginnt. Nach der Deklaration und Erzeugung des Arrays steht eine festgelegte Anzahl von Schubladen zur Verfügung, die nicht mehr geändert werden kann. Der festgelegte Datentyp ist sozusagen der Schlüssel um diese Schubladen zu öffnen und einen bestimmten Wert oder eine Referenz auf ein Objekt darin abzulegen. Der Vorteil von Arrays gegenüber einer entsprechenden Anzahl einfacher Variablen ist, dass Arrays sich leicht mit Schleifen bearbeiten lassen, da der Index einer Array-Komponente eine Variable sein kann und als Laufvariable in einer Schleife benutzt werden kann.
Inhaltsverzeichnis |
Deklaration, Erzeugung und Initialisierung eines Arrays
Die Definition einer Array-Variablen bedeutet in Processing nicht das Anlegen eines Arrays, sondern die Definition einer Referenzvariablen, die auf ein Array-Objekt zeigen kann.
Die allgemeine Form der Definition einer Referenzvariablen zum Zugriff auf ein Array lautet:
- Datentyp [ ] Arrayname;
Beispiele: int [ ] fibonacci, double [ ] messwert, String [ ] wort
Zum Erzeugen des Array-Objekts gibt es zwei Möglichkeiten:
- das Array mit new dynamisch erzeugen und anschließend die Elemente mit den gewünschten Werten initialisieren:
//Deklaration der Arrayvariable int [] evenNumber; void setup(){ //Erzeugung des Arrays evenNumber = new int [5]; //Initialisierung des Arrays evenNumber[0] = 2; evenNumber[1] = 4; evenNumber[2] = 6; evenNumber[3] = 8; evenNumber[4] = 10; //Ausgabe des Arrays auf der Konsole for(int i=0; i<5; i++){ println(evenNumber[i]); } }
- das Array über eine Initialisierungsliste anlegen und gleichzeitig initialisieren:
int [] evenNumber = {2,4,6,8,10};
Beachte: Eine Array-Variable ist eine Referenz auf ein Array-Objekt. Mit der Deklaration einer Array-Variable ist aber das Array-Objekt selbst noch nicht angelegt.
Arrays und Schleifen
Felder und Schleifen sind in der Programmierung eng verbunden. Wir verwenden Felder um die Vielzahl von Werten, die beim Durchlauf einer Schleife entstehen, zu speichern. Oder wir benutzen Schleifen um Felder zu initialisieren oder um Werte aus einem Array auszulesen.
Beispiel für die Initialisierung:
In einem Array sollen alle geraden Zahlen bis 100 abgespeichert werden.
//Deklarieren der Arrayvariable int [ ] gerade; void setup(){ //Erzeugung des Arrays int [ ] gerade = new int [50]; //Initialisieren des Arrays mittels einer Schleife for(int i=0; i<gerade.length; i++) { gerade[i] = 2+ i*2;} }
Beispiele für das Auslesen:
Mit einer weiteren Schleife können wir das erzeugte Array auf der Konsole ausgeben:
//Deklarieren der Arrayvariable int [ ] gerade; void setup(){ //Erzeugung des Arrays int [ ] gerade = new int [50]; //Initialisieren des Arrays mittels einer Schleife for(int i=0; i<gerade.length; i++) { gerade[i] = 2+ i*2;} //Ausgabe des Arrays auf der Konsole for(int i=0; i<gerade.length; i++) { println(gerade[i]);} }
Wir können den Inhalt des Arrays jedoch auch für Berechnungen nutzen.
Aus einem Array sollen Zahlen ausgelesen werden und ihr Mittelwert errechnet werden.
Hinweis: Mit der Methode Arrayname.length kann auf die Länge des Arrays zugegriffen werden.
//Deklarieren der Arrayvariable int [ ] zahlen; void setup(){ //Initialisierung des Arrays int [ ] zahlen = {3, 2, 5, 4, 1, 6}; //Einführung einer Hilfsvariable für die Summe float summe = 0; //Berechnung der Summe for (int i=0; i<zahlen.length; i++){summe = summe+zahlen[ i ];} //Berechnung des Mittelwerts float mittelwert = summe / zahlen.length; //Ausgabe des Ergebnisses auf der Konsole print(mittelwert); }
Aufgabe 1
Die ersten 20 Fibonacci-Zahlen sollen mit Hilfe eines Arrays erzeugt und ausgegeben werden. Dazu benötigen wir ein Array vom Typ long (geeignet für große (ganze) Zahlen). Die ersten beiden Fibonacci-Zahlen (0; 1) müssen "von Hand" eingegeben werden. Anschließend können wir die restlichen Elemente des Feldes mit Hilfe einer Schleife, die die weiteren Zahlen berechnet, belegen. Wir brauchen nun keine eigenen Variablen mehr, die sich bei jedem Durchlauf verändern, sondern wir greifen einfach auf die bereits belegten Elemente zu (Fibonacci (i)=Fibonacci(i-1)+Fibonacci(i-2) !!). Anschließend verwenden wir wiederum eine Schleife um die Inhalte des Feldes auf der Konsole auszugeben.
Aufgabe 2
Gesucht ist eine Methode, die die ersten 10 Potenzen einer Zahl, die in einer Variable basis festgehalten wird, in einem Array abspeichert. Als Datentyp sollte long verwendet werden. Zusätzlich ist folgender Zusammenhang zu beachten: pot [0]=1; pot [ i ] = pot [i-1]*Basis. Die zehn Zahlen sollen anschließend auf der Konsole ausgegeben werden.
Arrays in Graphikaufgaben
Arrays eignen sich natürlich auch hervorragend für die Lösung von graphischen Problemen in Processing. Sehen wir uns dazu folgendes Programm an, in dem ein Geist dem Mauszeiger folgt.
int[] xPos = new int[50]; int[] yPos = new int[50]; void setup(){ size(400, 400); frameRate(100); //Initialisierung der Arrays for(int i = 0; i < xPos.length; i++){ xPos[i] = 0; yPos[i] = 0; } } void draw(){ background(0); //Bei jeder Aktualisierung bekommt ein Kreis als neue Position die des ursprünglich folgenden for(int i = 0; i < xPos.length-1; i++){ xPos[i] = xPos[i + 1]; yPos[i] = yPos[i + 1]; } //Der letzte (= vorderste) Kreis bekommt als Mittelpunkt die Mausposition xPos[xPos.length - 1] = mouseX; yPos[yPos.length - 1] = mouseY; //Die Kreis werden mit der jeweils aktuellen Position gezeichnet for(int i = 0; i < xPos.length; i++){ //Kopf bzw. Rumpf noStroke(); fill(255); ellipse(xPos[i], yPos[i], 50, 60); //Augen stroke(0); strokeWeight(5); point(xPos[i]-10, yPos[i]-5); point(xPos[i]+10, yPos[i]-5); //Mund ellipse(xPos[i], yPos[i]+15, 4, 7); } }
Der Schlüssel der Darstellung ist die Zuweisung der neuen Position für die Einzelkreise, die den Geist bilden. Dabei erhält jeder Kreis den Mittelpunkt des Kreises, der ursprünglich vor ihm lag, wodurch in der Summe die Schlange entsteht, die dem Mauszeiger folgt.
Arrays aus Objekten
Besonders interessant werden Arrays dort, wo ihre Elemente Objekte sind. Wir können das Programm "Ufo Attack" aus dem letzten Kapitel dadurch deutlich kürzer gestalten. In der Klasse Ufo sind dabei nur kleinere Anpassungen, die die Datentypen betreffen, notwendig.
//Deklarieren der Arrayvariable Ufo [] attack; void setup(){ size(600, 400); background(255); //Erzeugen des Arrays attack = new Ufo[5]; //Initialisieren des Arrays über eine Schleife. Die Ufos erhalten eine zufällige Position, Größe und Bewegungsrichtung for(int j=0; j<attack.length; j++){ attack[j] = new Ufo(random(300)+150, random(200)+100, random(70), color(random(256), random(256), random(256)), random(4));}; } void draw(){ background(0); //Darstellen und Bewegen der Ufos. Geschwindigkeit wird zufällig auf einen Wert zwischen 2 und 7 gesetzt. for(int i=0; i<attack.length; i++){ attack[i].display(); attack[i].move(random(5)+2); } } class Ufo { //Attribute float xPos; float yPos; float b; color farbe; //Datentyp float für r, da r im Konstruktoraufruf im Hauptprogramm zufällig erzeugt wird und ein Randomwert vom Typ float ist float r; //Konstuktor Ufo(float xPos, float yPos, float b, color farbe, float r){ this.xPos = xPos; this.yPos = yPos; this.b = b; this.farbe = farbe; this.r = r; } void display(){ noStroke(); //Rumpf fill(farbe); ellipse(xPos, yPos, b, 4*b/5); ellipse(xPos, yPos, b*2.5, b/4); //Fenster fill(255); ellipse(xPos-b/5-2, yPos-b/5, b/5, b/5); ellipse(xPos, yPos-b/5, b/5, b/5); ellipse(xPos+b/5+2, yPos-b/5, b/5, b/5); } void move(float v){ b +=v; //Die Funktion floor() rundet r auf einen ganzzahligen Wert ab if(floor(r)==0){xPos -=7; b = b + xPos/b;}; if(floor(r)==1){xPos +=8; b = b + xPos/b;}; if(floor(r)==2){yPos -=7; b = b + yPos/b;}; if(floor(r)==3){yPos +=9; b = b + yPos/b;}; if(xPos<0||xPos>width||yPos<0||yPos>height){xPos = width/2; yPos = random(300)+100; b=0; farbe = color(random(256), random(256), random(256));}; } }
Aufgabe 3
Auf der Zeichenfläche erscheint eine festgelegte Anzahl von Kreisen, die zunehmend größer und transparenter werden. Sobald sie nicht mehr sichtbar sind, tauchen sie an anderer Position wieder auf und das Spiel beginnt von Neuem. Die Attribute und Methoden der Kreise werden in einer eigenen Klasse Kreis festgelegt (Klassendiagramm siehe unten). Im Hauptprogramm wird die Aufgabe mit einem Array von Kreis-Objekten gelöst.
Aufgabe 4
Ausgehend von Aufgabe 4b) aus dem Kapitel "Bedingungen" soll sich nun eine größere Zahl von Bällen auf der Zeichenfläche bewegen. Dabei sollen die Bälle nicht nur vom Rand abprallen, sondern auch bei der Kollision mit anderen Bällen. Diese Kollision mit anderen Bällen wird in der draw()-Funktion des Hauptprogramms realisiert und benötigt die bereits bekannte dist()-Funktion.
Aufgabe 5
Drei aus Punkten gebildete Kreise rotieren um einen gemeinsamen Mittelpunkt. Zum Erstellen der Kreise nutzen wir jeweils ein Array aus Punkten. Jeder dieser Punkte besitzt eine Position auf der Kreisbahn, die von seinem Anfangswinkel abhängt, der bei der Initialisierung der Arrays festgelegt wird. (Hinweis: Die Punkte müssen gleichmässig auf 360 Grad verteilt werden.). Als Ausgangspunkt nutzt man am besten das Beispiel zur Bewegung auf der Kreisbahn aus dem Kapitel "Methoden".