Schleifen in Processing: Unterschied zwischen den Versionen

Aus ComeniusWiki
Wechseln zu: Navigation, Suche
(Äquivalenz von for- und while-Schleife)
(Äquivalenz von for- und while-Schleife)
Zeile 628: Zeile 628:
  
 
<div style="margin-left:200px;">{{#ev:youtube |hoTtr9wHqvg|410}}</div>
 
<div style="margin-left:200px;">{{#ev:youtube |hoTtr9wHqvg|410}}</div>
 +
 +
 +
'''Aufgabe 9'''
 +
 +
Erstelle ein Programm, in dem du eine Kugel eine Treppe hinabrollen lässt. Nutze zur Darstellung der Treppe eine for-Schleife. Für das Herabrollen der Kugel benötigst du die [https://processing.org/reference/modulo.html Modulo-Funktion].
 +
 +
 +
<div style="margin-left:200px;">{{#ev:youtube |l_wT11WWJkE|410}}</div>
 +
 +
 +
<popup name="Lösungsvorschlag">
 +
<syntaxhighlight lang="java">
 +
//Variablen für den Startwert der Kugel
 +
float x = 20;
 +
float y = 0;
 +
 +
void setup(){
 +
  size(400, 200);
 +
  background(0);
 +
}
 +
 +
void draw(){
 +
 
 +
  background(0);
 +
  fill(200);
 +
  noStroke();
 +
  //Zeichnen der Treppe
 +
  for(int i=0; i<width; i+=20){   
 +
    rect(i*2, height-i, width-i*2, 20);
 +
  }
 +
 
 +
fill(255, 0, 0);
 +
ellipse(width-x, y, 40, 40);
 +
//Bei % handelt es sich um die Modulo-Funktion; steuert den Fall auf die nächste Stufe
 +
//x+=16 macht das Fallen auf die nächste Stufe realistischer
 +
if(x%40==0){x+=16; y+=20;};
 +
x++;
 +
  }
 +
</syntaxhighlight>
 +
</popup>
 
</div>
 
</div>

Version vom 18. November 2015, 17:45 Uhr

Am Ende des Kapitels solltest du

  • den Schleifencharakter der draw()-Funktion verstehen und die Methoden frameRate(), loop() und noLoop() einsetzen können,
  • den Begriff der Laufvariable kennen,
  • while- und for-Schleifen zur Lösung von Problemen einsetzen können,
  • den Begriff der Inkrementierung bzw. der Dekrementierung von Laufvariablen verstehen,
  • mit Abbruchbedingungen für eine Schleife umgehen können,
  • verschachtelte for--Schleifen verwenden können,
  • wissen, wie man eine for- in eine while--Schleife überführt.

Schleifen sind Kontrollstrukturen, die die wiederholte Ausführung von Anweisungen steuern. Eine Art von Schleife ist uns bereits bekannt, ohne dass wir sie wirklich bewusst wahrgenommen haben. Es ist die draw()-Funktion.

Inhaltsverzeichnis

Die draw() - Funktion

Sehen wir uns einmal folgendes Beispiel an:


int x = 0;
 
void draw(){
  x= x + 2;
  print(x + "   ");
}


Wir haben hier sozusagen eine Endlosschleife, die uns alle geraden Zahlen auf der Konsole ausgibt. Endlosschleife deshalb, weil es keine Abbruchbedingung gibt, die das Programm nach einer bestimmten Zeit beendet. Bis wir das Programm selbst beenden, wird es 60 mal pro Sekunde Zahlen ausgeben. Es gibt aber trotzdem Steuermöglichkeiten für diese Schleife. Mit der bereits bekannten frameRate() können wir die Zahl der frames/s steuern und mit loop() bzw. noLoop() die Schleife starten und stoppen.

Das folgende Beispiel zeigt die Möglichkeiten auf:


int x = 0;
 
void setup() {
  size(400, 200);
  //Reduzieren der Wiederholungsrate/s
  frameRate(40);
}
 
void draw() {
  background(0);
  fill(255, 255, 0);
  x = x + 1;
  if (x > width) {
    x = 0;
  }
  ellipse(x, 100, 20, 20); 
}
 
//Bei gehaltener Maustaste stoppt die Bewegung
void mousePressed() {
  noLoop();
}
 
//Beim Loslassen der Maustaste bewegt sich der Kreis weiter
void mouseReleased() {
  loop();
}

Beim Einsatz von Schleifen innerhalb der draw()-Funktion müssen wir ihren Schleifencharakter immer berücksichtigen, da wir sonst unter Umständen unliebsame Überraschungen erleben könnten. Dies liegt daran, dass die Funktion ihre Anweisungen bei jeder Aktualisierung ganz abarbeitet. Sollten also unerwartete Fehler auftreten, liegt das häufig an dieser Tatsache. Wenden wir uns nun aber den "echten" Schleifen zu.

Die while-Schleife

Die while-Schleife ähnelt stark der if-Bedingung, nur dass hier die Anweisungen innerhalb des Rumpfes solange wiederholt werden, wie die Überprüfung der Bedingung den Wert true ergibt. In Processing sieht diese Anweisung folgendermaßen aus:

while(Ausdruck){Anweisung}

Wir können diese Struktur auch in Form eines Ablaufdiagramms darstellen:

Proc loop 1.JPG


In einem ersten Beispiel lassen wir mittels einer while-Schleife die Zahlen 1 bis 10 auf der Konsole ausgeben:


void setup() {
  //Initialisierung der Laufvariable
  int i = 1;
  //while-Schleife mit Abbruchbedingung
  while(i<=10){
    //Ausgabe des aktuellen Wertes der Laufvariable
    println(i);
    //Aktualisierung der Laufvariable
    i++;
  }
println("Ich bin fertig!"); 
}

Erläuterungen:

  • Um Problem mit der draw()-Funktion zu vermeiden und da wir das Zeichenfenster nicht benötigen, schreiben wir die Anweisungen in die setup()-Funktion.
  • Die Variable i fungiert als Laufvariable. Sie wird mit dem Wert 1 initialisiert und bei jedem Durchlauf durch die Schleife um 1 erhöht (inkrementiert). Der Ausdruck i++ ist dabei die Kurzform für i=i+1, d.h. der Variable i wird jeweils der aktuelle Wert von i plus 1 zugewiesen. Entsprechend kann man noch andere Inkrementierungen bilden: i+=2 steht z.B. für i=i+2, i-=3 steht für i=i-3.
  • Bei jedem Durchlauf der Schleife wird der aktuelle Wert von i mittels der println-Funktion auf der Konsole ausgegeben..
  • Bei jedem Durchlauf wird der Ausdruck i<=10 ausgewertet und die Berechnung wird solange wiederholt, solange die Auswertung true ergibt.
  • Wenn die Auswertung false ergibt, wir die Schleife verlassen und auf der Konsole Vollzug gemeldet.


Hier noch zwei graphische Beispiele für den Einsatz der while-Schleife:


Proc loop 2.JPG
void setup() {
  size(400, 200);
  background(0);
  stroke(255,255,0);
}
 
void draw(){
  int i = 10;
  while(i<width){
    line(i, 0, i, height);
    i+=10;
  }
}


Proc loop 3.JPG
void setup() {
  size(200, 200);
  background(0);
  stroke(255,255,0);
}
 
void draw(){
  int i = 10;
  int j = 10;
  while(i<width){
    line(i, 0, i, height);
    line(0, j, width, j);
    i+=10;
    j+=10;
  }
}


Aufgabe 1

a) Erzeuge folgendes Muster mit Hilfe einer while-Schleife:


Proc loop 4.JPG



b) Wenn man mit diesem Muster herumspielt, d.h. mit den Parameterwerten experimentiert, kann man sehr interessante dynamische Muster erzeugen. Das Geheimnis dahinter ist die Tatsache, dass die draw()-Methode eigentlich auch eine Schleife ist.




Weitere Anregungen für Computerkunst zeigt das folgende Video


Aufgabe 2

Erstelle mit Hilfe einer while-Schleife ein Programm, das ein Band aus zufällig gefärbten Rechtecken durchlaufen lässt.


Proc loop 7.JPG



Aufgabe 3

Erzeuge mittels einer Folge von senkrechten Linien und einer while-Schleife einen Farbverlauf.


Proc loop 5.JPG



Aufgabe 4

Erzeuge mittels einer Folge von Kreisen und einer while-Schleife die Illusion einer Kugel:


Proc loop 6.JPG



Jede while-Schleife kann in eine etwas kompaktere Form überführt werden - die sogenannte for-Schleife.

Die for-Schleife

Die for-Schleife, oder auch Zählschleife, wird meist verwendet, wenn die Anzahl der Schleifendurchläufe im Vornhinein feststeht, wobei man eine sogenannte Laufvariable verwendet, um die Anzahl der Schleifendurchläufe zu zählen.


for(Initialisierungsteil; Abbruchbedingung; Inkrementierungsteil) {Anweisung}
  • Im Initialisierungsteil, der vor Betreten der Schleife ausgeführt wird, bekommt die Laufvariable ihren Wert.
  • Die Abbruchbedingung wir jedesmal vor Betreten der Schleife geprüft.
  • Der Inkrementierungsteil wird am Ende des Schleifendurchlaufs ausgeführt und erhöht oder verringert den Wert der Laufvariable.

Das Ablaufdiagramm der for-Schleife sieht folgendermaßen aus:


Proc loop 8.JPG


Beispiel:

Das folgende kleine Programm summiert die Zahlen von 1 bis 100 auf und gibt das Ergebnis auf der Konsole aus.


void setup(){
 
//Hilfsvariable zum Abspeichern der Zwischenergebnisse
int sum=0;
 
//Aufsummieren der Zahlen von 1 bis 100
for(int i=1;i<=100;i++){sum=sum+i;};
 
//Ausgabe des Ergebnisses (letzter aktueller Wert von sum
println("Die Summe der Zahlen 1 bis 100 ist "+sum);
}


Erläuterung der Schleife:

  • Im Initialisierungsteil wird die Laufvariable i auf den Anfangswert 1 gesetzt. Dabei ist zu beachten, dass der Datentyp int wie bei jeder Deklaration einer Variable angegeben werden muss.
  • Die Abbruchbedingung lautet i<=100.
  • Im Inkrementierungsteil wir die Laufvariable jeweils um 1 erhöht (i++).
  • Nach Verlassen der Schleife wird der aktuelle Wert von sum auf der Konsole ausgegeben.


Die Umsetzung der graphischen Beispiele aus dem Abschnitt über die while-Schleife sieht dann so aus:

void setup() {
  size(400, 200);
  background(0);
  stroke(255,255,0);
}
 
void draw(){
 for(int i=10; i<width; i+=10){
    line(i, 0, i, height);
  }
}


bzw.


void setup() {
  size(200, 200);
  background(0);
  stroke(255,255,0);
}
 
void draw(){
  for(int i=10; i<width; i+=10){
    line(i, 0, i, height);
  }
 
  for(int j=10; j<height; j+=10){
    line(0,j,width,j);
  }
}


Verschachtelung von for-Schleifen

Um beispielsweise interessante Muster zu erzeugen, kann man for-Schleifen auch ineinander verschachteln. Betrachten wir dazu folgendes Beispiel:


Proc loop 9.JPG
void setup() {
  size(200, 200);
  background(200);
  stroke(255,0,0);
  strokeWeight(5);
}
 
void draw(){
  for(int x=20; x<width; x+=20){
     for(int y=20; y<height; y+=20){
        point(x, y);
      }    
    }
}


Erläuterung:

Die äußere Schleife legt den x-Wert der ersten Reihe von Punkten fest. Die innere Schleife zeichnet nun alle 20px einen Punkt (Änderung des y-Werts). Nach Abarbeitung der inneren Schleife springt das Programm wieder in die äußere Schleife und ändert den x-Wert um 20px. Daraufhin zeichnet die innere Schleife die zweite Reihe von Punkten, usw. Nach Erreichen der Abbruchbedingung der ersten Schleife bricht das Programm ab.


Im Prinzip kann man beliebig viele Schleifen ineinander verschachteln. Zu beachten ist dabei, dass mit der Zahl der Schleifen unter Umständen die Laufzeit des Programms deutlich zunimmt. Hier noch ein schönes Beispiel:


Proc loop 10.JPG
void setup() {
  size(200, 200);
  background(200);
  stroke(255,0,0);
  strokeWeight(1);
}
 
void draw(){
  //Rechtecke im Modus "Ankerpunkt im Zentrum"
  rectMode(CENTER);
 
  background(255);
  for(int y=9; y<height; y+=20){
     for(int x=9; x<width; x+=20){
         for(int d = 18; d>0; d-=4){
            rect(x, y, d, d); 
         }
      }    
    }
}


Aufgabe 5

Experimentiere mit dem letzten Programmbeispiel um weitere Muster zu erzeugen. Beispiele:


Proc loop 11.JPG
Proc loop 12.JPG
Proc loop 13.JPG
Proc loop 14.JPG

Äquivalenz von for- und while-Schleife

Eine for-Schleife kann jederzeit in eine while-Schleife überführt werden. Dazu wird die Zählvariable außerhalb der while-Schleife initialisiert und am Ende des Anweisungsblocks aktualisiert. Die Abbruchbedingung steht wie üblich in der Klammer nach dem Schlüsselwort while.

Beispiel:

for(int i=1;i<=10;i++){Sequenz} 

kann übersetzt werden in:

int i=1;
while(i<=10){Sequenz;i++}


Aufgabe 6


Erzeuge folgenden Effekt mit Hilfe von zwei for-Schleifen:


Proc loop 15.JPG



Aufgabe 7

Erstelle ein Programm für folgendes Grundmuster (Bild links) mit Hilfe einer Schleife und variiere dann dieses Grundmuster (wie im Bild rechts):


Proc loop 16.JPG
Proc loop 17.JPG



Aufgabe 8

a) Schreibe ein Programm, das senkrechte Linien von links nach rechts bewegt. Hinweis: Nach jedem Durchlauf der Schleife, die die Linien zeichnet, muss der Startwert für x leicht erhöht werden.


b) Nutze die Grundidee um psychadelic patterns (siehe Video) zu erstellen.



Aufgabe 9

Erstelle ein Programm, in dem du eine Kugel eine Treppe hinabrollen lässt. Nutze zur Darstellung der Treppe eine for-Schleife. Für das Herabrollen der Kugel benötigst du die Modulo-Funktion.