Greenfoot: Schleifen

Werbung
Greenfoot: Schleifen
Kommen wir noch einmal zurück zu dem langweiligen, aber schön einfachen ausgabe_in_konsole-Szenario
(öffnen Sie es, speichern Sie ggf. eine Kopie des momentanen Zustands, dann löschen Sie allen Code, den Sie
bisher hineingeschrieben haben).
Sie haben ja bereits herausgefunden, wie man mithilfe einer Instanzvariable – also eine Variable, die in der
grünen Klassenklammer, nicht aber in einer der gelben Methodenklammern deklariert wird - die Ausgabe
einer fortlaufenden Zahlenreihe programmiert. Bis jetzt war es aber nötig, für jede Zahl einmal auf die ActSchaltfläche zu drücken.
Jetzt hätten wir gerne, dass ein einziger Aufruf der act()-Methode eine Zahl gleich mehrfach ausgibt, z.B.:
7777777777
Die Frage ist also, wie wir dem Computer sagen, er soll mehrmals dasselbe tun, z.B. den Befehl
System.out.print(meineZahl + “ “); ausführen.
1. Die for-Schleife
Die Antwort: mit einer Schleife. Genau genommen gibt es mehrere Arten von Schleifen, wenn ich bereits im
voraus weiss, wie oft ich etwas machen will, dann ist die for-Schleife am praktischsten. In Java formuliert
man das so:
for (int i = 1; i<=10; i++){
//zähle i von 1 bis 10
//hier steht der Code, der 10 mal ausgeführt werden soll
}
Schauen wir uns das etwas genauer an: ähnlich wie bei Verzweigungen steht der (hier: zu wiederholende)
Code in einem eigenen Block, also in geschweiften Klammern. Davor werden die Bedingungen für das
Wiederholen festgelegt: for gibt die Art der Schleife an und muss gefolgt werden von drei Argumenten,
eingeschlossen in normale Klammern und getrennt von Semikolons:

An der ersten Stelle wird die Zählvariable initialisiert, hier benutzen wir eine Ganzzahl i, die anfangs
auf den Wert 1 gesetzt wird.

An der zweiten Stelle steht das Abbruchkriterium, ähnlich wie bei Verzweigungen muss hier ein
Wahrheitswert (also true oder false) herauskommen. Im Beispiel steht hier i<=10, das bedeutet,
solange der Wert der Zählvariable i kleinergleich 10 ist wird der Code immer wieder ausgeführt.

An der dritten Stelle steht ein Befehl, der bei jeder Wiederholung der Schleife einmal ausgeführt wird.
Der Eintrag im Beispiel (i++) ist eine Kurzform von i = i +1 (das würde ebenfalls funktionieren), es
wird also nach jedem Durchgang der Wert der Zählvariablen i um 1 erhöht.
Auf diese Weise haben wir den Computer angewiesen, den Codeblock zehnmal auszuführen: Beim ersten
Durchgang ist i = 1; wird aber dann auf 2 gesetzt, bevor der Code erneut ausgeführt wird, beim dritten
Durchgang haben wir dann schon eine 3, ... , und wenn i schliesslich nicht mehr kleinergleich 10 ist (also nach
dem zehnten Durchgang), dann wird der Code in den geschweiften Klammern nicht erneut ausgeführt,
sondern es geht unterhalb der schliessenden geschweiften Klammer weiter.
Um die obige Ausgabe zu erreichen, müssten wir also folgendes in die act()-Methode schreiben:
for (int i = 1; i<=10; i++){
System.out.print(7 + “ “); //gibt eine 7 und ein Leerzeichen aus
}
System.out.println(“ “);
//damit die nächste Ausgaben in eine neue Zeile kommt
Probieren Sie das doch gleich mal aus.
Wenn Sie das obige Beispiel mit ihrem Wissen über Instanzvariablen kombinieren, dann sollten Sie auch ganz
leicht zu folgender Ausgabe kommen (eine Zeile pro act()-Aufruf):
1111111111
2222222222
3333333333
....
In der folgenden Variante wird die Zählvariable gleich noch innerhalb des Code-Blocks benutzt, das ist oft
sehr praktisch. Versuchen Sie zuerst herauszufinden, wie die Ausgabe aussehen wird, danach probieren Sie es
aus:
for (int i = 1; i<=10; i++){
System.out.print(i + “ “);
}
Und wie sieht es mit dieser Variante aus?
for (int i = 10; i>0; i=i-2){
System.out.print(i + “ “);
}
2. Die while-Schleife
Eine weitere Art von Schleife, die häufig benutzt wird, ist die while-Schleife. Hier ist die Anzahl der
Wiederholungen nicht im vorhinein festgelegt, sondern der Code wird so lange immer wieder abgearbeitet, bis
eine Bedingung (wie bei der Verzweigung) false ergibt. Besonders nützlich ist das, wenn man weiss wann die
Wiederholung aufhören soll, aber zu bequem ist auszurechnen, wie viele Repetitionen es dafür braucht, z.B.:
int meineZahl = 3;
while (meineZahl < 1000){
System.out.println(meineZahl);
meineZahl = meineZahl * meineZahl;
}
Wie Sie hier vielleicht schon sehen, lassen sich die meisten for-Schleifen auch als while-Schleifen
formulieren und umgekehrt, meist kann man sich also aussuchen, mit welcher Art man besser zurecht kommt.
Die erste Variante oben sähe als while-Schleife bspw. so aus:
int i = 1; // hier muss man die Zählvariable selbst kreieren und verwalten
while (i <= 10){
System.out.print(i + “ “);
i++;
//wieder die Kurzform, das Hochzählen darf man nicht vergessen!
}
Da die Syntax von Schleifen am Anfang etwas gewöhnungsbedürftig ist, passieren hier oft kleine Fehler.
Einige der üblichsten finden Sie bei den Anfängerfehlern (auf dem Wiki), vielleicht hilft das bei der
Vermeidung.
3. Aufgaben zu Schleifen (Konsolenausgabe)
1) Schreiben sie ein Programm, das mithilfe einer while-Schleife die Zahlen 2 bis 20 ausgibt.
2) Ändern sie den Code aus Aufgabe 1) so ab, dass dieselbe Ausgabe mithilfe eine while-Schleife entsteht.
3) Benutzen Sie eine beliebige Schleife, um die Siebenerreihe (zwischen 0 und 100) auszugeben.
4) Benutzen Sie eine beliebige Schleife, um die Dreiherreihe rückwärts (zwischen 30 und 0) auszugeben.
5) Schreiben Sie ein Programm, das die Summe der ganzen Zahlen von 1 bis 100 mit einer Schleife
berechnet und ausgibt.
6) Schreiben Sie ein Programm, das die Summe der Quadratzahlen von 1 bis 10 mit einer Schleife berechnet
und ausgibt.
7) Ein Programm soll zuerst von 0 bis 0, dann von 0 bis 1, dann von 0 bis 2, dann 0 bis 3, usw., bis 0 bis 9
zählen. Die Ausgabe soll so aussehen (eine Zeile pro act()-Aufruf):
0
01
...
0123456789
Hinweis: Sie haben oben schon gesehen, wie man in einer Zeile bis zu einer bestimmten Zahl hochzählt. Das
müssen Sie jetzt nur noch kombinieren mit einer Instanzvariablen für die aktuelle Obergrenze, die selbst bei
jedem act()-Aufruf um 1 inkrementiert (erhöht) wird.
8) Entwickeln Sie Programme, die die angegebenen Sternchenmuster auf möglichst einfache Weise unter
Benutzung von Zählschleifen ausgeben (eine Zeile pro act()-Aufruf):
1.
****
****
****
****
2.
*
**
***
****
*****
3.
****
***
**
*
4.
**
****
******
********
5.
*
**
***
**
*
9) Schreiben Sie ein Programm das eine Schleife benutzt, um folgende Ausgabe zu erzeugen:
1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024,
10) Das kleine 1x1 soll in zehn Zeilen ausgegeben wrden, ungefähr so:
1 2 3 4 5 6 7 8 9 10
2 4 6 8 10 12 14 16 18 20
3 6 9 12 15 ....
Hinweis: Das geht sehr ähnlich wie in den obigen Aufgaben, aber schaffen Sie es auch, dass alle zehn Zeilen
auf einmal ausgegeben werden, wenn man einmal auf Act() drückt?
11) Schaffen Sie es mithilfe der folgenden Informationen und einer Schleife, ihren Namen rückwärts
auszugeben?
String meinName
= „Nicolas Ruh“;
String erstesZeichen = meinName.substring(0,1); //gibt das erste Zeichen
//(Position 0 bis 1) von meinName zurück
System.out.print(meinName.substring(1,2)); //gibt das zweite Zeichen aus
4. Turtle Joe
Nun wird es aber wirklich Zeit, dass wir uns mit etwas anderem als Konsolenausgaben beschäftigen. Dafür
gibt es ein neues Szenario namens Joe – wie üblich müssen Sie es herunterladen, entpacken und in Greenfoot
öffnen.
Abb 1: So sollte das Szenario zu Beginn aussehen, es passiert noch nichts, wenn man auf den Act-Knopf drückt.
In diesem Szenario gibt es einen Actor namens Turtle (Schildkröte), und ihre Aufgabe wird es sein, eine
spezielle Turtle mit Namen Joe so zu programmieren, dass er/sie/es bestimmte Figuren zeichnet.
Da Sie jetzt nicht mehr mit Zahlen und Buchstaben, sondern mit Joe arbeiten wollen, müssen Sie zunächst
herausfinden, was Joe eigentlich kann - also welche Befehle Sie ihm geben können. Joe funktioniert im
allgemeinen ähnlich wie der Wombat, den Sie ja schon ein wenig kennen, aber es gibt doch ein paar
Unterschiede. Woher also weiss man, wie man Joe benutzt?
Grundsätzlich gilt: jede Klasse hat die Fähigkeiten ihrer Oberklassen – die Klassen sieht man im obigen Bild
in den Rechtecken rechts, die Hierarchie ist mit Pfeilen dargestellt. Also: eine Turtle ist ein spezieller Actor,
sie kann alles was ein Actor kann und hat noch dazu ein paar eigene Fähigkeiten (= Methoden). Joe ist eine
spezielle Turtle, er erbt alle Fähigkeiten sowohl von Turtle als auch von Actor – und vielleicht verleihen Sie
ihm dazu noch ein paar eigene, z.B. indem Sie seine act()-Methode verändern.
Will man herausbekommen, welche Fähigkeiten vorgegeben sind, sollte man sich die Dokumentation der
jeweiligen Klasse ansehen (z.B. Rechts-Klick auf Actor  Open Documentation). Die für die folgenden
Aufgaben wichtigsten Methoden habe ich ihnen hier zusammengestellt:
Gegeben ist eine Klasse Turtle, die u.a. folgende Methoden zur Verfügung stellt:
void moveAndDraw(int distance)
Bewegt die Turtle geradeaus und zeichnet gleichzeitig eine Line in der aktuellen Stiftfarbe
void moveToAndDraw(int newX, int newY)
Bewegt die Turtle zu den angegebenen Koordinaten und zeichnet gleichzeitig eine Line in der
aktuellen Stiftfarbe
void setColor(String newColor)
Ändert die Stiftfarbe. Möglich: "red", "black", "blue", "yellow", "green", "magenta", "white", "gray"
In der Actor-Klasse sind seit der Greenfoot-Version 2.1 u.a. die folgenden praktischen Methoden definiert:
void
move(int distance)
Move this actor the specified distance in the direction it is currently facing.
void
setLocation(int x, int y)
Assign a new location for this actor.
void
turn(int amount)
Turn this actor by the specified amount (in degrees)
Sie sehen, dass nach dem Methodennamen (z.B. move) in Klammern ein oder mehrere Variablentypen und –
namen angegeben sind (z.B. int distance). Den Namen (plus die Klammern) braucht es immer, um eine
Methode aufzurufen, also auszuführen. Wenn in den Klammern noch etwas steht, dann heisst das, diese
Methode braucht noch zusätzliche Informationen um zu funktionieren; z.B. muss move() noch wissen, wie
weit die Bewegung gehen soll (distance) und diese Distanzangabe muss ausserdem eine int, also ein
ganzzahliger Wert sein. Um die Methode zu benutzen muss ich also lediglich dafür sorgen, dass in den
Klammern ein ganzzahliger Wert steht, dann erfolgt eine Bewegung über die entsprechende Distanz. Wenn
ich also will, dass Joe sich um 10 Pixel geradeaus bewegt, dann brauche ich den Befehl move(10); wenn er
gleichzeitig noch einen Strich zeichnen soll, benutze ich moveAndDraw(10); mit turn(90); bringe ich Joe
dazu, sich um 90 Grad (im Uhrzeigersinn) zu drehen. Anstatt den Wert direkt in die Klammern zu schreiben
kann ich natürlich auch eine Variable angeben, die einen Wert des entsprechenden Typs (hier: int) enthält.
Wie Sie oben sehen gibt es auch noch eine Methode setColor(), die Informationen in Form eines Strings
erwartet. Mit dem Befehl setColor(„red“); kann ich also dafür sorgen, dass Joe in Zukunft rote Striche
zeichnet – zumindest so lange, bis ich die Farbe wieder ändere.
Wenn ich keinen Wert übergebe, obwohl einer erwartet wird (z.B. move();) oder wenn der übergebene Wert
einen falschen Typ hat (z.B. move(„ABC“);), dann bekomme ich einen Fehler beim Kompilieren – was ja
auch Sinn macht.
Ein einfaches Beispiel, etwas sehr ähnliches haben Sie im Wombat-Szenatio ja auch schon programmiert:
public void act() //das ist die act()-Methode der Klasse Joe
{
for (int i=0; i<4; i++){
if (i%2==0){
//wenn i gerade ist
setColor("blue");
} else {
setColor("red");
}
moveAndDraw(100);
turn(90);
}
}
Vielleicht überlegen Sie zunächst, was dieser Code wohl bewirken könnte und probieren es dann aus.
So, und nun versuchen Sie sich selbst am Figurenzeichnen mit Schleifen:
5. Turtle Aufgaben
1. Ausgehend vom letzten Beispiel: ändern Sie den Code so ab, dass Joe kein
Quadrat, sondern ein Dreieck zeichnet.
2. Ändern Sie Joes act()-Methode so, dass Joe beim Aufruf der Methode
GENAU das rechtsstehende Bild produziert (die innerste, kürzeste Linie ist 10
Pixel lang, jede weitere ist um 10 Pixel länger als die Vorhergehende).
3. Ändern Sie Joes act()-Methode so, dass Joe beim
Aufruf der Methode GENAU das rechtsstehende Bild
produziert (die Seitenlänge eines Quadrats ist 30 Pixel,
der Abstand zwischen Quadraten ebenfalls).
4. Ändern Sie Joes act()-Methode so, dass Joe beim Aufruf der Methode GENAU
das rechtsstehende Bild produziert (Strichlänge ist je 100 Pixel).
5. Ändern Sie Joes act()-Methode so, dass Joe beim Aufruf der Methode GENAU
das rechtsstehende Bild produziert (die Strichlängen sind 10 resp. 100 Pixel).
Herunterladen
Explore flashcards