Funktionen: Aufgaben
Der Hamster möchte sein (leeres) Territorium vermessen.


Schreibe ein entsprechendes Programm. Beginne mit folgendem Grundgerüst und ergänze bei // TODO.
void main()
{
int breite = laufeZurWandUndBestimmeAbstand();
linksUm();
int hoehe = laufeZurWandUndBestimmeAbstand();
schreib("Ich habe " + breite + "x" + hoehe + " gemessen.");
}
int laufeZurWandUndBestimmeAbstand()
{
// TODO
}
Orientiere dich bei der Definition der laufeZurWandUndBestimmeAbstand-Funktion an der nimmUndZaehle-Funktion aus dem Beispiel. Dort werden Körner gezählt... hier werden Schritte gezählt.
void main()
{
int breite = laufeZurWandUndBestimmeAbstand();
linksUm();
int hoehe = laufeZurWandUndBestimmeAbstand();
schreib("Ich habe " + breite + "x" + hoehe + " gemessen.");
}
int laufeZurWandUndBestimmeAbstand()
{
int n = 0;
while (vornFrei())
{
vor();
n++;
}
return n + 1;
}
Der Hamster will Gold sammeln. Dazu läuft er seine ganze Reihe ab. Auf den Kacheln befindet sich entweder nichts, Schrott (ein einzelnes Korn) oder Goldklumpen (zwei Körner). Er soll nur das Gold einsammeln und zählen, wie viele Goldklumpen er aufgenommen hat. Diese Zahl soll er mit einem Befehl wie schreib("Ich habe " + goldAnzahl + " Goldklumpen gefunden!"); ausgeben.
Schreibe ein Programm, welches die Aufgabe löst. Tipp: Verwende die folgende Funktion zweiKornDa .
boolean zweiKornDa()
{
if (kornDa())
{
// Es ist mindestens ein Korn da.
// Nimm ein Korn auf, um nun einen Blick auf ein moegliches
// zweites Korn zu werfen.
nimm();
// Nun pruefen und speichern, ob ein zweites Korn auch noch da ist.
boolean zweitesKornDa = kornDa();
// Genommenes Korn wieder zuruecklegen.
gib();
return zweitesKornDa;
}
else
{
// Es ist gar kein Korn da.
return false;
}
}
Verwende eine Variable goldAnzahl zum Zählen der Goldklumpen. Mit einer while-Schleife lässt du den Hamster die ganze Reihe durchlaufen. Bei jedem Schritt prüfst du nun, ob sich ein Goldklumpen auf der aktuellen Kachel befindet − falls ja, inkrementiere die Variable goldAnzahl.
void main()
{
int goldAnzahl = 0;
while (vornFrei())
{
vor();
if (zweiKornDa())
{
goldAnzahl++;
}
}
schreib("Ich habe " + goldAnzahl + " Goldklumpen gefunden!");
}
boolean zweiKornDa()
{
if (kornDa())
{
// Es ist mindestens ein Korn da.
// Nimm ein Korn auf, um nun einen Blick auf ein moegliches
// zweites Korn zu werfen.
nimm();
// Nun pruefen und speichern, ob ein zweites Korn auch noch da ist.
boolean zweitesKornDa = kornDa();
// Genommenes Korn wieder zuruecklegen.
gib();
return zweitesKornDa;
}
else
{
// Es ist nicht mal ein Korn da.
return false;
}
} Der Hamster will seine Körnerwaage bedienen. Es gibt zwei vor ihm liegende Felder, die gegeneinander abgewogen werden sollen. Im Folgenden sollen z.B. 3 Körner gegen 8 Körner abgewogen werden.
Betrachte das folgende Progamm. Erkläre, wie die Waage funktioniert.
Ergänze anschließend den // TODO-Teil zur Gewichtsbestimmung.
void main()
{
vor();
int a = bestimmeGewicht();
vor();
int b = bestimmeGewicht();
if (a > b)
{
schreib("Links schwerer");
}
else
{
schreib("Rechts schwerer oder gleich schwer");
}
}
int bestimmeGewicht()
{
int n = 0;
// TODO
return n;
}ErweiterungErweitere die Waage so, dass zwischen den folgenden drei Ergebnissen unterschieden wird:
- Links ist schwerer
- Rechts ist schwerer
- Waage ist im Gleichgewicht
void main()
{
vor();
int a = bestimmeGewicht();
vor();
int b = bestimmeGewicht();
if (a > b)
{
schreib("Links schwerer");
}
else
{
schreib("Rechts schwerer oder gleich schwer");
}
}
int bestimmeGewicht()
{
int n = 0;
while (kornDa())
{
nimm();
n++;
}
return n;
}
void main()
{
vor();
int a = bestimmeGewicht();
vor();
int b = bestimmeGewicht();
if (a > b)
{
schreib("Links schwerer");
}
else if (a < b)
{
schreib("Rechts schwerer");
}
else
{
schreib("Gleichgewicht");
}
}
int bestimmeGewicht()
{
int n = 0;
while (kornDa())
{
nimm();
n++;
}
return n;
} Der Hamster will die Lücken in der Mauer zählen.
Schreibe ein entsprechendes Programm. Verwende die im Beispiel definierte Funktion linksFrei. Der Hamster soll zum Schluss sein Ergebnis mit schreib("Ich habe " + anzahl + " Luecken gezaehlt."); mitteilen.
void main()
{
int zaehler = 0;
while (vornFrei())
{
vor();
if (linksFrei())
{
zaehler++;
}
}
schreib("Es sind " + zaehler + " Luecken!");
}
boolean linksFrei()
{
linksUm();
boolean frei = vornFrei();
rechtsUm();
return frei;
}
void rechtsUm()
{
linksUm();
linksUm();
linksUm();
} In dieser Aufgabe soll der Hamster gar keine Aktionen ausführen. Stattdessen soll er folgendes machen:
- Den Benutzer/in nach der Breite und der Höhe eines Rechtecks fragen.
- Den Umfang $u$ und den Flächeninhalt $A$ des Rechtecks berechnen.
- Den Umfang und den Flächeninhalt ausgeben.
Verwende das folgende Grundgerüst. Das "\n" sorgt für einen Zeilenumbruch (new line). Ergänze die beiden // TODOs.
Tipp: Bitte nicht irritieren lassen − die Aufgabe ist sehr leicht; es geht hier lediglich darum, mit Funktionen vertraut zu werden.
void main()
{
int b = liesZahl("Bitte Breite eingeben:");
int h = liesZahl("Bitte Hoehe eingeben:");
int umfang = berechneUmfang(b, h);
int flaecheninh = berechneFlaecheninh(b, h);
schreib("u = " + umfang + "\n" +
"A = " + flaecheninh);
}
int berechneUmfang(int breite, int hoehe)
{
// TODO
}
int berechneFlaecheninh(int breite, int hoehe)
{
// TODO
}
void main()
{
int b = liesZahl("Bitte Breite eingeben:");
int h = liesZahl("Bitte Hoehe eingeben:");
int umfang = berechneUmfang(b, h);
int flaecheninh = berechneFlaecheninh(b, h);
schreib("u = " + umfang + "\n" +
"A = " + flaecheninh);
}
int berechneUmfang(int breite, int hoehe)
{
return 2*breite + 2*hoehe;
}
int berechneFlaecheninh(int breite, int hoehe)
{
return breite*hoehe;
}
Definiere eine Funktion int zaehle(), welche so wie int nimmUndZaehle() funktioniert, jedoch die Körner nach dem Zählen wieder zurücklegt. Wichtig: Erst nach dem Zurücklegen kann die Anzahl mit return zurückgeliefert werden, da die return-Anweisung die letzte Anweisung im Funktionsrumpf sein muss.
Nach Aufruf von zaehle sieht das Territorium also genau so aus, wie vor dem Aufruf von zaehle. Man sagt auch, dass zaehle keine Seiteneffekte hat (im Gegensatz dazu hat nimmUndZaehle den Seiteneffekt, alle Körner auf der aktuellen Kachel dauerhaft zu entfernen).
Mit anderen Worten:
- Zwei Aufrufe von
zaehleliefern dieselbe Zahl zurück. - Zwei Aufrufe von
nimmUndZaehleliefern beim ersten Mal die Anzahl zurück, und beim zweiten Mal 0 zurück, da die Körner nach dem ersten Zählvorgang abgeräumt werden.
Teste deine Funktion, indem du die beiden Funktionen nimmUndZaehle und zaehle gegenüberstellst.
void main()
{
vor();
int anzahlA = zaehle();
int anzahlB = zaehle();
vor();
int anzahlC = nimmUndZaehle();
int anzahlD = nimmUndZaehle();
schreib("zaehle: " + anzahlA + " und " + anzahlB);
schreib("nimmUndZaehle: " + anzahlC + " und " + anzahlD);
}
int zaehle()
{
// TODO
}
int nimmUndZaehle()
{
// TODO (s.a. Beispiel)
}
Z.B. sollten bei rechtsstehendem Territorium die Variablen anzahlA, anzahlB und anzahlC den Wert 5 enthalten, während anzahlD den Wert 0 enthält.
void main()
{
vor();
int anzahlA = zaehle();
int anzahlB = zaehle();
vor();
int anzahlC = nimmUndZaehle();
int anzahlD = nimmUndZaehle();
schreib("zaehle: " + anzahlA + " und " + anzahlB);
schreib("nimmUndZaehle: " + anzahlC + " und " + anzahlD);
}
int zaehle()
{
// Sammle und zaehle dabei (so, wie immer)
int anzahl = 0;
while (kornDa())
{
nimm();
anzahl++;
}
// Koerner wieder ablegen
for (int i = 0; i < anzahl; i++)
{
gib();
}
// Wert zurueckgeben
return anzahl;
}
int nimmUndZaehle()
{
// Sammle und zaehle dabei (so, wie immer)
int anzahl = 0;
while (kornDa())
{
nimm();
anzahl++;
}
// Wert zurueckgeben
return anzahl;
}
Betrachte die Funktion laufeZurWandUndBestimmeAbstand aus der Aufgabe „Vermessungshamster“. Die Funktion lässt den Hamster bis zur Wand laufen und lierfert die Anzahl der Schritte bis zur Wand zurück.
Ändere die Funktion so ab, dass der Hamster vor dem Zurückliefern der Schrittzahl noch zum Ausgangspunkt zurückläuft. Erst danach soll der return-Befehl ausgeführt werden.
In dieser Aufgabe soll der Hamster gar keine Aktionen ausführen. Stattdessen soll er sich rechnerisch betätigen:
- Den Benutzer/in nach einer Zahl fragen und sie in der Variablen
nspeichern. (Tipp: Verwende denliesZahl-Befehl). - Die Potenz $n^{16}$ berechnen und in der Variablen
ergebnisspeichern. - Den Wert der Variablen
ergebnismitschreibausgeben.
Betrachte die folgenden zwei Möglichkeiten, die Potenz zu berechnen.
- Einfacher Ansatz: $\text{ergebnis} = n^{16} = n \cdot n \cdot n \cdot n \cdot n \cdot n \cdot n \cdot n \cdot n \cdot n \cdot n \cdot n \cdot n \cdot n \cdot n \cdot n$
- Cleverer Ansatz: $\text{ergebnis} = n^{16} = (n^{2})^{8} = ((n^{2})^2)^{4} = (((n^{2})^2)^2)^2$
Probiere beide Ansätze für z.B. $n = 3$ aus.
- Einfacher Ansatz: $\text{ergebnis} = 3^{16} = 3 \cdot 3 \cdot 3 \cdot 3 \cdot 3 \cdot 3 \cdot 3 \cdot 3 \cdot 3 \cdot 3 \cdot 3 \cdot 3 \cdot 3 \cdot 3 \cdot 3 \cdot 3 = 43046721$
- Cleverer Ansatz: $\text{ergebnis} = 3^{16} = (3^{2})^{8} = 9^{8} = (9^2)^{4} = 81^4 = (81^2)^2 = 6561^2 = 43046721$
Natürlich kommt dasselbe heraus. Warum ist der zweite Ansatz „clever“? Anstatt $n$ 16 Mal mit sich selbst zu multiplizieren (viel Arbeit), müssen wir nur 4 Mal eine Quadratzahl ausrechnen, also nur 4 Multiplikationen ausführen (wenig Arbeit).
Definiere die Funktion int quadrat(int x), welche für eine gegebene Zahl $x$ die Quadratzahl $x^2$ berechnet.
Schreibe nun das Programm mit dem cleveren Ansatz: int ergebnis = quadrat(quadrat(quadrat(quadrat(n))));