Übungen zu Kapitel 3(noch in arbeit)

17-08-2011 13:00 von NachoMan

Mit Verzweigungen kannst du auf die Eingaben des Benutzers reagieren. Das ermöglicht dir, kleine Spiele zu schreiben. Ich habe mir ein "Textadventure" ausgedacht, damit du dir einfacher vorstellen kannst wie das Programm gesteuert wird, und es so übst.

Aufgabe nach Kapitel 3.5 (Voraussetzung: Bedingungen und else if):
Anmerkungen:

Wenn du programmierst, solltest du das in kleinen Schritten tun und möglichst oft testen. Wenn du direkt nach einer Erweiterung einen Fehler entdeckst, weißt du noch genau, was du geändert hast und kannst den Fehler einfacher eingrenzen. Ausserdem sinkt die Wahrscheinlichkeit dafür, dass du mehrere Fehler in einem Schritt machst. Wenn dir das passiert, könntest du einen Fehler beheben und merken, dass es immer noch nicht funktioniert und den behobenen Fehler wieder rein schreiben. Selbst wenn ein einzelner Fehler in nur 10 Minuten behoben wäre, könntest du für zwei Fehler mehrere Stunden brauchen. Da kann man ruhig ein paar mal öfter 20 Sekunden zum Testen opfern.

Ich werde die Aufgabe, die schon recht komplex ist, wieder in mehrere Teile zerlegen. Das hilft dir dabei kleine Schritte zu machen und du weißt besser, wo du anfangen kannst. Ich gebe dir Fluss- oder Aktivitätsdiagramme, die dir den genauen Programmablauf zeigen. Die Aufgabe in Textform zu erklären wäre unmenschlich. Ich habe sie übrigens mit Violet gezeichnet. Dieses Programm ist gratis verfügbar und sehr komfortabel.

Aufgabe:

Programmiere ein Textadventure mit folgenden Abläufen:

Teil 1:  

Meine ausführbare Version.

Anmerkung: 

Es fängt gleich etwas Kompilizierter an. Hier solltest du erstmal die Möglichkeit ignorieren, dass die Person verdurstet. Damit brauchst du nur ein if+Bedingung. Wenn das funktioniert kannst du die fehlerhafte Eingabe des Benutzers (ein Wert über 100) behandeln.

Nachdem du eine Lösung gefunden hast kannst du versuchen eine Lösung zu finden, in der Zeilen, in denen eine Meldung gemacht wird, nicht doppelt vorkommen. Man sollte also eine Meldung im Diagramm einer bestimmten Zeile zuweisen können. Das erhöht die Erweiterbarkeit und macht den Code übersichtlicher. Dafür benötigst du wahrscheinlich ein verschachteltes elseif.

Mein Lösungsvorschlag:

Link

Teil 2:

tl_files/nachoman/images/uebungkapitel3teil2.JPG

Meine ausführbare Version.

Mein Lösungsvorschlag:

Link

Teil 3 (Voraussetzung: logische Operatoren "&&" und "||"):

tl_files/nachoman/images/uebungkapitel3teil3.JPG

Meine ausführbare Version.

Mein Lösungsvorschlag:

Link

Anmerkung:

Ich hoffe du hattest keine großen Probleme und du hast jetzt ein Gefühl für Verzweigungen und ihre Verschachtelung bekommen. Schreibe bitte einen Kommentar wenn du alles gründlich gelesen und trotzdem noch Fragen hast.

Aufgaben nach Kapitel 3.8 (Voraussetzung: for-Schleifen)

Teil 1:

Nun hast du ein sehr mächtiges Werkzeug kennengelernt, mit dem du dir sehr viel Arbeit sparen kannst. Ich fang wieder ganz einfach an und mach es immer schwieriger.

Aufgabe:

Gebe alle Zahlen von 0 bis einschließlich 42, getrennt von einem Backslash "\", mit Hilfe einer for-Schleife aus. Die Ausgabe darf ruhig mit einem Backslash enden.

Tipp:

Denk an die Escapezeichen...

Mein Lösungsvorschlag:

Link

Anmerkung: 

Hier benötigen wir ein <= weil wir 42 mit einschließen. Wir machen also 43 Schleifendurchgänge. Man könnte auch < 43 schreiben, aber das ist weniger gut verständlich. Für uns ist die 42 wichtig und nicht die 43. Ausserdem müssen wir '\\' schreiben um ein einzelnes Backslash auszugeben. Das liegt daran, dass das Backslash normalerweise ein Escapezeichen anzeigt. Wenn du nun "c:\nacho" schreiben wolltest, würde er einen Zeilenumbruch ausgeben. Also musst du "c:\\nacho" schreiben. Ausserdem nutze ich hier ++i(Präinkrement) anstelle von i++(Postinkrement). In dem Fall gibt es zwar keinen Unterschied aber man sollte sich meine Variante angewöhnen, weil Postinkrement manchmal langsamer ist und für Anfänger unerwartetes Verhalten ausweist. Dazu ein kleiner Beispielcode:

Int i = 0;
std::cout << ++i << std::endl; // Ausgabe: 1
std::cout << i++ << std::endl; // Ausgabe: 1
std::cout << i << std::endl; // Ausgabe: 2
Steht das ++ vor der Variable, wird sie erst erhöht ("prä" steht für "vor", wie in "Prähistorisch") und dann der neue Wert übergeben. Steht es hinter der Variable ("post" steht für "nach", wie in "postapokalyptisch") wird der alte Wert übergeben und danach die Variable erhöht.
Teil 2:
Ein großes Problem für viele Programmieranfänger ist der Gültigkeitsbereich von Variablen. Steht ihre Definition innerhalb von geschweiften Klammern { } sind sie darüberhinaus nicht gültig. Werden sie innerhalb von Schleifen definiert sind sie nur für einen Schleifendurchlauf gültig. Willst du also einen Wert aus dem ersten Durchlauf im zweiten nutzen musst du die Variable vor der Schleife definieren. Der Initialisierungsteil der for-Schleife gilt als vor der Schleife, die Variable bleibt also für alle Schleifendurchgänge gültig. Allerdings ist sie hinter der Schleife nicht mehr gültig, man kann also nicht drauf zugreifen.
Aufgabe:
Frage 5 Zahlen mit Hilfe einer Schleife vom Benutzer ab und gebe ihre Summe und den abgerundeten Durchschnittswert aus. Achte dabei darauf die Variablen so spät wie möglich zu Definieren.
Mein Lösungsvorschlag:
Anmerkung:
Das einzige, was hier vielleicht "besonders" sein könnte, ist die Konstante numOfIteration. Man könnte stattdessen auch zwei mal einfach 5 schreiben. Will man das Programm später so ändern, dass es sieben Zahlen abfragt muss man etwas an zwei Stellen ändern. Vergisst man dabei eine Fünf zu ändern hat man einen Fehler, der schwer aufzufinden ist. Ausserdem spart man sich durch die Konstante einen Kommentar. "sum/numOfIterations" sagt wesentlich mehr über den nutzen einer Operation aus als "sum/5" und ein erfahrener Programmierer sieht sofort, dass es sich um den Durchschnittswert handelt anstatt sich zu fragen, was die Fünf heißen soll.
Teil 3(noch nicht fertig): 
Als ich überlegt habe, wie ich die Aufgaben zum Thema Schleifen spannender machen kann als einen Countdown oder das Summieren von Zahlenreihen, hat mein Mathelehrer mich mit seinem Unterricht unterbrochen und gefragt wie ich eine bestimmte mathematische Funktion zeichnen würde. Nach 10 Sekunden an der Tafel hatte ich eine Idee und eine gute mündliche Note. Das Zeichnen von Funktionensgraphen an sich ist nicht so schwierig. Wenn man es nicht zu genau nimmt muss man nur Punkte der Funktion berechnen und diese mit einer Linie verbinden. Allerdings stand ich vor dem Problem, dass ich keine zusätzliche Graktikbibliothek verwenden will, die du dir erstmal herunterladen und einrichten musst. Also blieb mir nichts anderes übrig als es dich in der Konsole als ASCII Grafik zeichnen zu lassen. Das ist aber ganz und garnicht mehr einfach. Also habe ich Funktionen geschrieben, die dir so gut wie alles abnehmen. Du musst nur den Bereich angeben, der angezeigt werden soll und einige Punkte berechnen und übergeben. Um die Funktionen nutzen zu können kopierst du dir diese Quelldatei und bearbeitest nur die Mainfunktion, die ganz unten steht. Bitte versuch nicht den Code drüber zu verstehen. Direkt über der Mainfunktion stehen erklärungen zu den Funktionen.
Beispiel:
Du leihst dir einen Film in der Videothek. Für den ersten Tag zahlst du 2.00€, für jeden weiteren 1.50€. Der Preis in abhängigkeit der Tage lässt sich als Funktion darstellen.
y = 1.50*x+0.50
Dabei steht x für die Tage und y für den Preis. 1.50*x sorgt für den Tagespreis, das +0.50 brauchen wir damit der erste Tag 2.00€ kostet. Zeichnet man sich nun ein Koordinatensystem, berechnet y für x = 1 und y für x = 10, trägt beide Punkte ein und verbindet sie mit einer Geraden, kann man den Preis für jede andere Dauer ganz leicht ablesen.
tl_files/nachoman/images/linearefunktion.JPG
Zeichnung der Funktion y = 1.50*x+0.50 wie im Bild.
Im Anzeigebereich: -2.0f, 10.f, 10.0f, -2.0f
Für das Beispiel wird keine Schleife benötigt.
Beispiel: Link
Ich habe nur die Mainfunktion gepostet. Du kannst deine Mainfunktion einfach durch sie ersetzen und das Programm starten.
Aufgabe: 
Stell dir vor du stehst an einer hohen Klippe und wirfst ein sehr schweres, aber kleines Smartphone eines beliebigen Herstellers hinunter. Die Gravitation an der Klippe beträgt 9.81m/s² und du kannst die Luftreibung vernachlässigen. Zeichne einen Graphen für die Aufprallgeschwindigkeiten in Abhängigkeit der höhe der Klippe. Die Formel ist:
v = sqrt(2*gravitation*fallhöhe)
tl_files/nachoman/images/klippenfunktion.jpg
Anzeigebereich: -2.0f, 15.f, 10.0f, -2.0f
Für diese Aufgabe wirst du eine einfache Schleife benötigen. Mach am besten Einserschritte von 0 bis 20. Rechne mit einem Ortsfaktor(Gravitation) von 9,81m/s².
Mein Lösungsvorschlag:
Aufgabe:
Du wurdest von der NASA eingstellt und da sie, wie jeder weiß, Apple abgrundtief hasst, bekommst du die Aufgabe zu berechnen, wie schnell das iPhone auf verschiedenen Planeten aufprallen würde. Die Formel ist immernoch:
v = sqrt(2*gravitation*fallhöhe)
Allerdings ist der Ortsfaktor ebenfalls Variabel. Da wir nicht in der Lage sind dreidimensionale Diagramme zu zeichnen, müssen wir eine Serie von diagrammen zeichnen. Dafür wirst du eine äußere Schleife für die Gravitation und eine innere für die Fallhöhe benötigen. Ausserdem musst du in jedem durchlauf die Funktion neu Zeichnen und alle Punkte löschen(mit plotter.render() und plotter.clearField()).
Der Anzeigebereich bleibt: -2.0f, 15.f, 10.0f, -2.0f
Zeichne die Serie an Bildern in Einserschritten für die Ortsfaktoren 1 bis 20.
Mein Lösungsvorschlag:
Anmerkung:
Du solltest Fließkommazahlen nur dann mit == oder != vergleichen, wenn du weißt, dass vorher eine Zuweisung mit diesem Wert stattgefunden hat hat. Ansonsten solltest du immer einen Zahlenbereich angeben.Wenn du etwas berechnest, bei dem du 0 erwartest, könnte es passieren, dass du durch Rundungsfehler auf 0.0002 kommst. Wenn du dann einen Vergleich mit 0 machst wird es falsche Ergebnisse geben. In dem Fall schreibt man anstelle von (kommazahl == 0) (kommazahl > -0.01 && kommazahl < 0.01). Problem beseitig. :D
 Mein Lösungsvorschlag:

Zurück

Einen Kommentar schreiben

Kommentar von Benno | 05-01-2012

Sehr Hilf- und Lehrreiche Aufgaben !
°_°