In der E-Phase habt ihr Arrays kennen gelernt. Wie war das nochmal?
- Lest euch das Fachkonzept: Array und das Fachkonzept: for-Schleife durch.
- Beantwortet die folgenden Fragen:
- Was ist ein Array?
- Welche Arten von Daten können in Arrays gespeichert werden?
- Wie werden Daten in Arrays gespeichert? Wie werden sie abgerufen?
- Was unterscheidet die for- von der while-Schleife?
- Warum ist es im Kontext von Arrays sinnvoller, eine for-Schleife statt einer while-Schleife zu verwenden?
In einer vorherigen Lektion habt ihr die Blubbels kennen gelernt.
Rechts seht ihr einen Ausschnitt aus dem Quellcode.
- Überlegt euch, was passieren muss, wenn ihr einen neuen Blubbel (oder 2, 3, 100?!) hinzufügen wollt.
Da stellt sich doch die Frage, ob das nicht auch einfacher geht?!
Sketch
Blubbel b1 = new Blubbel(100, 10, 3); Blubbel b2 = new Blubbel(200, 8, 2); Blubbel b3 = new Blubbel(250, 12, 2); Blubbel b4 = new Blubbel(350, 9, 4); void setup() { size(400, 300); } void draw() { background(255); b1.display(); b1.aufsteigen(); b2.display(); b2.aufsteigen(); b3.display(); b3.aufsteigen(); b4.display(); b4.aufsteigen(); }
Blubbel
class Blubbel { float x; float y; float r; float v; Blubbel(float x, float r, float v) { this.x = x; this.r = r; this.v = v; y = height - r; } void display() { fill(color(0, 0, 255)); ellipse(x, y, r, r); } void aufsteigen(){ y = y - v; if (y < 0) { x = random(width - r); y = height; v = random(5); } } }
Den Blubbel-Sketch-Code von oben könntet ihr auch durch den Code rechts ersetzen. Hier wurden die einzelnen Blubbel-Variablen b1
, b2
, b3
und b4
durch den Blubbel-Array blubbels
ersetzt. Dieser wird in der setup()
-Methode mit Blubbel-Blasen gefüllt. Außerdem wurden die einzelnen Aufrufe für die display()
- und aufsteigen()
-Methoden durch eine for
-Schleife ersetzt.
Wenn wir nun einen neuen Blubbel hinzufügen wollen, müssen wir allerdings immer noch mehrere Stellen im Code anpassen. Das ist umständliche Schreibarbeit (man muss immer blubbels[i] = new Blubbel(…)
schreiben und die Array-Größe anpassen). Es geht aber auch einfacher:
Blubbel[] blubbels = new Blubbel[] { new Blubbel(100, 10, 3), new Blubbel(200, 8, 2), new Blubbel(250, 12, 2), new Blubbel(350, 9, 4) }; void setup() { size(400, 300); }
Mit dieser Kurzform wird der Array blubbels
automatisch mit passender Größe deklariert und die einzelnen Felder mit Blubbel-Blasen gefüllt. Möchte man nun einen neuen Blubbel hinzufügen, muss man ihn nur noch im Array anlegen (siehe rechts), den Rest übernimmt Java automatisch.
Blubbel[] blubbels = new Blubbel[4]; void setup() { size(400, 300); blubbels[0] = new Blubbel(100, 10, 3); blubbels[1] = new Blubbel(200, 8, 2); blubbels[2] = new Blubbel(250, 12, 2); blubbels[3] = new Blubbel(350, 9, 4); } void draw() { background(255); for (int i = 0; i < blubbels.length; i++) { blubbels[i].display(); blubbels[i].aufsteigen(); } }
Blubbel[] blubbels = new Blubbel[] { new Blubbel(100, 10, 3), new Blubbel(200, 8, 2), new Blubbel(250, 12, 2), new Blubbel(350, 9, 4), new Blubbel(50, 7, 6), // Erster neuer Blubbel new Blubbel(150, 12, 1) // Zweiter neuer Blubbel };
Das obige Beispiel zeigt, wie man Daten aus einem Array mit Hilfe einer for-Schleife auslesen kann. Hierzu ist einiges an Syntax notwendig. Man muss eine Hilfsvariable i
deklarieren, die von 0 bis zur Arraygröße hochgezählt wird. Danach muss man mit blubbels[i]
auf das i
-te Array-Element zugreifen. Ganz schön umständlich!
for (int i = 0; i < blubbels.length; i++) { blubbels[i].display(); blubbels[i].aufsteigen(); }
Um den Code etwas besser verständlich zu machen, lohnt es sich oft, eine weitere Variable blubb
einzuführen, damit man den Index blubbels[i]
nicht immer schreiben muss:
for (int i = 0; i < blubbels.length; i++) { Blubbel blubb = blubbels[i]; blubb.display(); blubb.aufsteigen(); }
Für dieses Konstrukt bietet Java eine einfachere Schreibweise, die for-each-Schleife. Hier wird für jede einzelne Blubbel-Blase die Schleife durchlaufen, und das aktuelle Arrayelement in der Variable blubb gespeichert.
for (Blubbel blubb : blubbels) { blubb.display(); blubb.aufsteigen(); }
Beide Konstrukte sind äquivalent. Eines davon (Tipp: die for-each-Schleife!) ist allerdings syntaktisch deutlich einfacher! Einziger Nachteil: man hat keinen direkten Zugriff mehr auf den Index des Elements. Dies kann (z.B. insbesondere bei Such- oder Sortierverfahren) nachteilig sein.
Passt die Ufo-Aufgabe (Aufgabe 3 aus Klassen und Objekte) so an, dass ein Array und eine for- oder eine for-each-Schleife verwendet wird.
Achtung Der Parameter v
der ursprünglichen move(int v)
-Methode muss zu einem Attribut der Klasse geändert werden!
Sketch
Ufo[] ufos = new Ufo[] { new Ufo(150, 100, 70, color(random(256), random(256), random(256)), 1, 3), new Ufo(200, 200, 30, color(random(256), random(256), random(256)), 2, 2), new Ufo(350, 200, 20, color(random(256), random(256), random(256)), 3, 3), new Ufo(450, 100, 60, color(random(256), random(256), random(256)), 0, 4), new Ufo(180, 300, 10, color(random(256), random(256), random(256)), 1, 5) }; void setup() { size(600, 400); background(255); } void draw() { background(0); for (Ufo ufo : ufos) { ufo.display(); ufo.move(); } }
Ufo
class Ufo { // Attribute float xPos; float yPos; float b; color farbe; int r; int v; // Konstuktor Ufo(float xPos, float yPos, float b, color farbe, int r, int v) { this.xPos = xPos; this.yPos = yPos; this.b = b; this.farbe = farbe; this.r = r; this.v = v; } 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() { b += v; if (r == 0) { xPos -= 7; b = b + xPos / b; } if (r == 1) { xPos += 8; b = b + xPos / b; } if (r == 2) { yPos -= 7; b = b + yPos / b; } if (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)); } } }
- Passt die Auto-Aufgabe (Aufgabe 4 aus Klassen und Objekte) so an, dass sie mehrere Arrays (je ein Array für Bäume, Häuser und Autos) und for(-each)-Schleifen verwendet.
- Fügt mehrere Autos hinzu.
Sketch
Haus[] haeuser = new Haus[] { new Haus(400, 100, 100, 100), new Haus(100, 100, 100, 100) }; Baum[] baeume = new Baum[] { new Baum(250, 200, 20, 40), new Baum(300, 180, 18, 36) }; Auto[] autos = new Auto[] { new Auto(50, 300, 3, color(255, 0, 0)), new Auto(150, 300, 3, color(0, 255, 0)), new Auto(250, 300, 3, color(0, 0, 255)), new Auto(150, 350, 5, color(255, 255, 0)), new Auto(250, 350, 5, color(0, 255, 255)), new Auto(350, 350, 5, color(255, 0, 255)) }; void setup() { size(600, 400); } void draw() { background(100); for (Haus haus : haeuser) { haus.display(); } for (Baum baum : baeume) { baum.display(); } for (Auto auto : autos) { auto.display(); auto.move(); } }
Baum
class Baum { // Attribute int x; int y; int breite; int hoehe; // Konstruktor Baum(int x, int y, int breite, int hoehe) { this.x = x; this.y = y; this.breite = breite; this.hoehe = hoehe; } // Methoden void display() { rectMode(CORNER); fill(255); rect(x, y, breite, hoehe); fill(0, 255, 0); triangle(x - breite * 2, y, x + breite / 2, y - hoehe * 3, x + breite * 3, y); } }
Haus
class Haus { // Attribute int x; int y; int breite; int hoehe; // Konstruktor Haus(int x, int y, int breite, int hoehe) { this.x = x; this.y = y; this.breite = breite; this.hoehe = hoehe; } // Methoden void display() { rectMode(CORNER); fill(255); rect(x, y, breite, hoehe); fill(255, 0, 0); triangle(x, y, x + breite / 2, y - hoehe / 3, x + breite, y); } }
Auto
class Auto { // Attribute int x; int y; int v; color c; // Konstruktor Auto(int x, int y, int v, color c) { this.x = x; this.y = y; this.v = v; this.c = c; } // Methoden void display() { rectMode(CENTER); noStroke(); fill(c); rect(x, y, 80, 20); ellipse(x, y - 10, 40, 40); fill(0); ellipse(x - 25, y + 10, 20, 20); ellipse(x + 25, y + 10, 20, 20); } void move() { x += v; if (x > width) { x = 0; } } }
Weihnachten.pde
- Weihnachten.pde
Snowflake[] snowflakes = new Snowflake[2000]; int lastFlakeIndex = -1; void setup() { size(640, 480); for (int i = 0; i <= 100; i++) { spawnNewFlake(); snowflakes[i].setY(random(height / 4)); } } void draw() { background(0); drawChristmasTree(); for (Snowflake flake : snowflakes) { if (flake == null) continue; flake.update(); flake.draw(); } spawnNewFlake(); } boolean canFallTo(int x, int y, float offset) { if (y >= height - offset) return false; color pixel = get(x, y); return pixel != #640909 && pixel != #FFFF00 && pixel != #1B7110 && pixel != #FF0000 && pixel != #990000; } void drawChristmasTree() { noStroke(); fill(#640909); rect(width / 2 - 10, height - 25, 20, 25); drawBranches(width / 2 - 100, height - 25, width / 2 + 100, height - 25, width / 2, height - 75, 3); drawBranches(width / 2 - 80, height - 50, width / 2 + 80, height - 50, width / 2, height - 100, 3); drawBranches(width / 2 - 60, height - 75, width / 2 + 60, height - 75, width / 2, height - 125, 2); drawBranches(width / 2 - 40, height - 100, width / 2 + 40, height - 100, width / 2, height - 150, 2); drawBranches(width / 2 - 30, height - 125, width / 2 + 30, height - 125, width / 2, height - 160, 2); fill(#FFFF00); drawStar(width / 2, height - 160, 20, 10, 6); } void drawBranches(int x1, int y1, int x2, int y2, int x3, int y3, int mod) { fill(#1B7110); triangle(x1, y1, x2, y2, x3, y3); for (int i = x1 + 10; i <= x2 - 10; i += 10) { fill(#FF0000); if ((i/10) % mod == 0) { fill(#990000); } circle(i, y1, 7); } } void drawStar(float x, float y, float radius1, float radius2, int nPoints) { float angle = TWO_PI / nPoints; float halfAngle = angle / 2.0; beginShape(); for (float a = 0; a < TWO_PI; a += angle) { float sx = x + cos(a) * radius2; float sy = y + sin(a) * radius2; vertex(sx, sy); sx = x + cos(a + halfAngle) * radius1; sy = y + sin(a + halfAngle) * radius1; vertex(sx, sy); } endShape(CLOSE); } void spawnNewFlake() { lastFlakeIndex++; if (lastFlakeIndex >= snowflakes.length) { lastFlakeIndex = 0; } int rg = 255 - int(random(96)); snowflakes[lastFlakeIndex] = new Snowflake(random(width), 0, 0.5 + random(1), 2 + random(3), color(rg, rg, 255)); }
Snowflake.pde
- Snowflake.pde
class Snowflake { private float posX, posY, velocity, size; private boolean hasFallen = false; private color col; public Snowflake(float posX, float posY, float velocity, float size, color col) { this.posX = posX; this.posY = posY; this.velocity = velocity; this.size = size; this.col = col; } public void draw() { fill(col); noStroke(); drawStar(posX, posY, size, size * 0.5, 8); } public void setY(float posY) { this.posY = posY; } public void update() { if (canFallTo(int(this.posX), int(this.posY + velocity), this.size / 2.0)) { this.posY += velocity; } else { hasFallen = true; } } public boolean hasFallen() { return this.hasFallen; } }