diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bdddb52..6cb5515 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,9 +6,10 @@ jobs: timeout-minutes: 30 steps: - name: Checkout - uses: actions/checkout@v2 - - uses: xu-cheng/texlive-action/full@v1 - with: + uses: actions/checkout@v4 + - uses: xu-cheng/texlive-action@v2 + with: + scheme: full run: | apk add make apk add g++ diff --git a/.gitignore b/.gitignore index 9e5b0dc..585224f 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,6 @@ vorkurs/ vorkurs.zip pool_setup/poolpw title.pdf +.vscode/ +.DS_Store +*.dSYM diff --git a/Makefile b/Makefile index 1f9f418..cfdb077 100644 --- a/Makefile +++ b/Makefile @@ -53,13 +53,8 @@ dir: files/* @cp files/vector.cpp vorkurs/lektion15/. > /dev/null @cp files/warnings.cpp vorkurs/lektion16/. > /dev/null @cp files/warnprim.cpp vorkurs/lektion16/. > /dev/null - @cp files/tictactoe.cpp vorkurs/lektion17/. > /dev/null + @cp files/tictactoe.cpp vorkurs/lektion14/. > /dev/null @cp files/assemble.cpp vorkurs/lektion18/. > /dev/null - @echo "TTT-Dateien kompilieren…" - @g++ -c -o vorkurs/lektion17/tictactoe.o files/ttt_closed/tictactoe.cpp > /dev/null - @g++ -c -o vorkurs/lektion19/frage_feld_nummer.o files/ttt_closed/frage_feld_nummer.cpp > /dev/null - @g++ -c -o vorkurs/lektion19/gewinnerin.o files/ttt_closed/gewinnerin.cpp > /dev/null - @g++ -c -o vorkurs/lektion19/gebe_feld_aus.o files/ttt_closed/gebe_feld_aus.cpp > /dev/null @echo "Vorkurs-Verzeichnis erstellt." @echo "Wenn du das Verzeichnis überall hin kopiert hast, nutze "make nodir", um sicherzustellen, dass das Skript nächstes Jahr wieder funktioniert" diff --git a/appendix/cheatsheet_shellcomands.tex b/appendix/cheatsheet_shellcomands.tex new file mode 100644 index 0000000..e69de29 diff --git a/appendix/cheatsheet_shortcuts.tex b/appendix/cheatsheet_shortcuts.tex new file mode 100644 index 0000000..e69de29 diff --git a/basics/style.tex b/appendix/coding_style.tex similarity index 100% rename from basics/style.tex rename to appendix/coding_style.tex diff --git a/appendix/error_messages.tex b/appendix/error_messages.tex new file mode 100644 index 0000000..e69de29 diff --git a/appendix/intro.tex b/appendix/intro.tex new file mode 100644 index 0000000..91fbe28 --- /dev/null +++ b/appendix/intro.tex @@ -0,0 +1,13 @@ +\chapter{Appendix} +\pagestyle{empty} + + +\pagestyle{fancy} +\input{appendix/cheatsheet_shortcuts} %ToDo needs to be added +\input{appendix/cheatsheet_shellcomands} % ToDo needs to be added +\input{appendix/coding_style} %ToDo, partially done +\input{appendix/error_messages} % ToDo needs to be added + +\clearpage +\pagestyle{empty} + diff --git a/basics/arrays.tex b/basics/arrays.tex deleted file mode 100644 index 61f204a..0000000 --- a/basics/arrays.tex +++ /dev/null @@ -1,85 +0,0 @@ -\lesson{\texttt{C}-Arrays} - -Als nächstes wichtiges Konzept in \Cpp werden wir uns \emph{Arrays} anschauen. -Arrays sind eine Möglichkeit, mehrere Elemente des gleichen Typs zusammen zu -fassen. Statt also einer Stelle im Speicher, an der ein \texttt{int} liegt, -habt ihr einen ganzen Speicherbereich, in dem 100 (oder eine beliebige andere -Anzahl an) \texttt{int}s liegen. - -Die Elemente in einem Array sind durchnummeriert, man nennt die Nummer eines -Arrayelements seinen \emph{Index}. Das erste Element hat den Index 0, das -zweite den Index 1 und das 100te hat den Index 99 -- Vorsicht also, der höchste -Index in einem Array mit 100 Elementen ist 99, nicht 100! Um ein Array zu -definieren, schreibt ihr hinter seinen Namen eine eckige Klammer auf, die -Anzahl an Elementen, die es enthalten soll, und eine eckige Klammer zu. Auf ein -bestimmtes Arrayelement zuzugreifen könnt ihr tun, indem ihr seinen Index in -eckigen Klammern hinter den Namen schreibt. Folgendes Programm macht -hoffentlich die Syntax klar: -\inputcpp{array.cpp} - -Es gibt einige Dinge, zu beachnten, wenn ihr mit Arrays arbeitet. Das -wichtigste ist oben schon genannt -- sich davon verwirren zu lassen, dass -Indizes bei 0 anfangen und aus Versehen über das Array hinaus schreiben oder -lesen ist ein so häufiger Fehler, dass er seinen eigenen Namen bekommen hat: -„Off-by-one error“. Wichtig ist, dass der Compiler diesen Zugriff nicht -verhindern wird! Das ist von daher eine sehr fiese Sache, als dass dieser -Fehler auch beim Ausführen nicht immer Probleme machen wird -- aber manchmal -lässt er auch euer Programm spontan abstürzen in einem so genannten -\emph{segmentation fault}. - -Eine Limitation von Arrays, die ihr beachten solltet, ist, dass bereits zur -Compilezeit fest stehen muss, wie viele Elemente sie enthalten sollen. Ihr -könnt also z.B. nicht die Nutzerin fragen, wie viele Elemente in das Array -passen soll, denn dies würde erst zur Laufzeit feststehen (wir werden später -noch Wege um diese Limitation kennen lernen). - -Ihr könnt auch Arrays von Arrays (so genannte zweidimensionale Arrays) -erstellen, indem ihr zweimal in eckigen Klammern die Größe des Arrays -hinschreibt. Die erste Größe gibt dann die Anzahl der Zeilen an, die zweite die -Anzahl der Spalten. Auch beim Zugriff auf Arrayelemente müsst ihr dann zwei -Indizes angeben. Wir werden dies später noch nutzen, hier sei erst einmal nur -die generelle Möglichkeit genannt. - -\textbf{Praxis:} -Wir wollen die Seite \url{http://www.ich-kann-mich-nicht-entscheiden.de/} -nachmachen und eine Entscheidungshilfe programmieren, die aus mehreren von der -Nutzerin gegebenen Möglichkeiten eine per Zufall auswählt. - -\begin{enumerate} - \item Schreibt zunächst ein Programm, welches ein Array aus 10 Strings - erstellt und die Nutzerin 10 mal nach einer Antwortmöglichkeit fragt - und die gegebenen Antworten nacheinander in das Array schreibt. - \item Fügt nun die Möglichkeit zu, weniger Antworten anzugeben. Dazu könnt - ihr zum Beispiel zuerst fragen, wie viele Antwortmöglichkeiten es geben - soll und dann so oft fragen (und natürlich einen Fehler ausgeben, wenn - es mehr als 10 Antworten geben soll). - \item Ihr könnt dann (so wie in dem Programm oben) eine Zufallszahl - erzeugen. Um sicher zu gehen, dass sie nicht zu groß wird, könnt ihr - den Rest bei Teilung durch Anzahl der eingegebenen Antworten nehmen - (sind z.B. 7 Antworten angegeben und die Zufallszahl ist 25778, so wäre - der resultierende Index \texttt{25778 \% 7 == 4}). Gebt dann die - Antwortmöglichkeit aus, die dem zufallsgeneriertem Index - entspricht. -\end{enumerate} - -Sollte euer Programm einmal nicht korrekt kompilieren, denkt daran die -Fehlermeldung sorgfältig zu lesen, damit sie euch Aufschluss über die -Fehlerursache gibt. Sollte euer Programm zwar kompilieren, sich dann aber -komisch verhalten, denkt daran, den debugger zu benutzen und es Schritt für -Schritt durchzugehen, um die Fehlerquelle zu finden. Solltet ihr trotz alledem -nicht weiter kommen, oder nicht wissen, was von euch erwartet wird, fragt einen -von uns. - -\textbf{Spiel:} -\begin{enumerate} - \item Schreibt ein Progamm, welches ein Array beliebiger Größe erstellt und - dann auf einen Index weit ausserhalb des erlaubten Bereichs schreibt. - Was beobachtet ihr?\footnote{Es wird natürlich Quark sein was dabei - rauskommt, es geht hier haupsächlich darum das ihr seht was für - einen Fehler das gibt} - \item Implementiert das \emph{Sieb des Eratosthenes} - \footnote{\url{https://de.wikipedia.org/wiki/Sieb_des_Eratosthenes}}, - wenn ihr noch nicht ausgelastet seid. - Denkt daran, es initial zu befüllen und denkt euch eine clevere - Möglichkeit aus, das „Streichen“ zu realisieren. -\end{enumerate} diff --git a/basics/tictactoe2.tex b/basics/tictactoe2.tex deleted file mode 100644 index 1244b89..0000000 --- a/basics/tictactoe2.tex +++ /dev/null @@ -1,50 +0,0 @@ -\lesson{Tic Tac Toe - Teil 2} - -Dies ist die letzte Lektion des ersten Kapitels. In der vorletzten Lektion -haben wir die grobe Struktur eines Tic Tac Toe Spiels implementiert, dafür -haben wir ein paar Funktionen benutzt, die uns gegeben waren. Nun wollen wir -diese Funktionen nachimplementieren („Implementieren“ heißt, dass man eine mehr -oder weniger formale Spezifikation in Programmcode umsetzt). Für eine -Beschreibung, was die Funktionen machen sollen, könnt ihr in der vorletzten -Lektion nachschauen. Damit ihr eure eigene Implementationen testen könnt, haben -wir noch einmal alle Funktionen mit beigefügt. Sie befinden sich in den Dateien -\texttt{frage\_feld\_nummer.o}, \texttt{gebe\_feld\_aus.o} und -\texttt{gewinnerin.o}. - -Um eine Funktion zu implementieren, solltet ihr die dazugehörige -\texttt{extern}-Deklaration aus eurer \texttt{tictactoe.cpp} löschen und dann -die Funktion mit dem gleichen Namen (und den gleichen Parametern und -Rückgabetypen) selbst definieren und implementieren. Ihr könnt, wenn ihr z.B. -\texttt{gewinnerin} selbst implementiert habt, euer Programm mit - -\texttt{g++ -o tictactoe tictactoe.cpp frage\_feld\_nummer.o gebe\_feld\_aus.o} - -kompilieren. Je mehr Funktionen ihr selbst nachimplementiert, desto weniger -gegebene \texttt{.o}-files müsst ihr natürlich angeben. - -Es gibt es dieses mal auch keine Nummern für die einzelnen Teile -- sucht euch -doch selbst aus, in welcher Reihenfolge ihr sie bearbeiten wollt, sie ist -ziemlich beliebig. Fangt am Besten mit dem Teil an, der euch am leichtesten -erscheint. - -\begin{praxis} - \begin{itemize} - \item Implementiert \texttt{frage\_feld\_nummer} nach. Ihr solltet darauf - achten, dass ihr in dieser Funktion auch testen müsst, ob ein gültiges - Feld eingegeben wurde und ob das angegebene Feld leer ist. - \item Implementiert \texttt{gebe\_feld\_aus} nach. Ihr könnt euch selbst - aussuchen, wie ihr die Ausgabe gestalten wollt -- es muss nicht genauso - aussehen, wie unser Vorschlag. Die - Wikipedia\footnote{\url{http://en.wikipedia.org/wiki/Box-drawing_character}} - kann euch z.B. helfen, ein schöneres Feld auszugeben. Fangt am Besten - mit einer einfachen Ausgabe an und macht sie dann immer „fancier“. - \item Implementiert \texttt{gewinnerin} nach. Bedenkt, dass ihr alle - Möglichkeiten testet, auf die ein Gewinn möglich ist -- also 3 - Möglichkeiten, eine Reihe zu bilden, 3 Möglichkeiten, eine Spalte zu - bilden und 2 Möglichkeiten für Diagonalen. Überlegt euch zunächst, wie - ihr zwischen Feldnummer (0-8) und Reihen- bzw. Spaltennummer hin- und - herrechnen könnt. Beachtet auch, dass es ein Unentschieden gibt, wenn - alle Felder belegt sind, aber keine von beiden Spielerinnen gewonnen - hat. - \end{itemize} -\end{praxis} diff --git a/classes/classes.tex b/classes/classes.tex deleted file mode 100644 index d9fded6..0000000 --- a/classes/classes.tex +++ /dev/null @@ -1,24 +0,0 @@ -\lesson{Klassen} - -Eine komplexere Art von Datentypen als Enums sind die sogenannten Klassen. Diese lassen sich als eine Art Gegenstand vorstellen, der verschiedene Eigenschaften hat. - -Wenn zum Beispiel eine Videothek ihre DVD-Sammlung verwalten möchte, wäre es eine Möglichkeit jede DVD durch eine Klasse darzustellen. Dabei ist die Klasse dann ein Bauplan für die späteren Datentypen, die erstellt werden. Diese DVD-Klasse könnte dann Attribute für den Titel, ob sie zurzeit ausgeliehen ist, eine Möglichkeit zu speichern, wann sie zurück gegeben werden muss, und einen Zähler, um zu speichern, wie oft die DVD schon ausgeliehen wird, enthalten. - -Nun wird es irgendwann passieren, dass jemand eine DVD ausleihen möchte. Dafür sollte es also eine leichte Möglichkeit geben, um den Ausleihstatus zu ändern und automatisch das Rückgabedatum auf einen sinnvollen Wert zu setzen. -Eine erfahrerne Benutzerin wird jetzt natürlich an Funktionen denken. Für die -Übersichtlichkeit des Programmes ist es sehr vorteilhaft, die Funktionen einer -Klasse zu bündeln. Dafür werden diese in der Klasse definiert und gehören so als -\emph{Memberfunktion} zur Klasse. - - -Eine Klasse kann Information haben, die für alle zugänglich sein sollten, und Informationen, die nicht oder nur eingeschränkt zugreifbar sein sollten. Zum Beispiel ist es sinnvoll, dass jede Benutzerin die Möglichkeit hat DVDs auszuleihen, deshalb wird die Methode ausleihen als \emph{public} definiert. -Da es aber auch klasseninterne Variablen und Funktionen gibt, wie hier zum -Beispiel die DVD-Sammlung selbst, ergibt es auch Sinn Teile der Klasse als -\emph{private} zu deklarieren. Wir modellieren also durch die Einteilung in public \& -private also Eigenschaften, die wir bisher nicht abbilden konnten. \\ -Per Default ist alles in einer Klasse \emph{private}. - -Jetzt gibt es auch noch weitere Attribute wie den Name der Sammlung, der nicht -so ganz in beide Kategorien passt. Da Benutzerinnen den Titel zwar auslesen müssen, aber den Titel nicht einfach verändern sollen. Dafür ist die übliche Vorgehensweise, \emph{getter}- bzw \emph{setter}-Methoden zu definieren. Eine getter-Methode sollte das entsprechende Attribut (zum Beispiel den Titel) zurückgeben. Wohingegen eine setter-Methode einen Parameter des Types des entsprechenden Attributes entgegen nimmt und dann den Wert intern ändert. - -\inputcpp{class.cpp} diff --git a/classes/content.txt b/classes/content.txt deleted file mode 100644 index e5cf8ef..0000000 --- a/classes/content.txt +++ /dev/null @@ -1,9 +0,0 @@ -Planung Kapitel 2 - -Enums, Casting + ANSI-Esc -for-Schleifen -Structs -Code-Snippets -C++11 (Funktionen), Aliase(Bash) -Klassen (Methoden, Private-Public) -STL (Vector, Array) diff --git a/classes/enum.tex b/classes/enum.tex deleted file mode 100644 index 36b0993..0000000 --- a/classes/enum.tex +++ /dev/null @@ -1,24 +0,0 @@ -\lesson{Enums \& Ansi} - -Da die Basics der \Cpp-Programmierung nun verinnerlicht sind, fangen wir an uns eigene Datentypen zu definieren. -Eine der einfachsten Kategorien von Datentypen sind \emph{Enum}s. Der Hauptzweck von Enums ist das Zuordnen von Bedeutungen zu Nummerierungen. -Sie ermöglichen z.B. das Verwenden von leicht lesbaren Begriffen an Stellen, die eigentlich ganze Zahlen erfordern. \\ -In folgendem Codebeispiel existiert eine Funktion \texttt{runden}, die abhängig der als \emph{mode} angegebenen Zahl entweder kaufmännnisch rundet, oder ab- bzw. aufrundet. - -\inputcpp{runden.cpp} - -Das ist relativ unschön und unintuitiv zu benutzen. Man weiß zum Beispiel nicht, wie viele modes es überhaupt gibt, wenn man den Code nicht genau ließt. Dies kann zu unnötigen Fehlern führen, wie man beim letzten Aufruf von \texttt{runden} sieht. Natürlich könnte man für den \emph{mode} auch den Typ String wählen, diese Verbrauchen aber sehr viel Platz und sind damit völlige Verschwendung für diese Aufgabe. Besser lässt sich das mit einem Enum lösen: - -\inputcpp{runden2.cpp} - -In den geschweiften Klammer wird angegeben, welche Zustände der Datentyp annehmen kann. -Intern werden diese von 0 beginnend durchnummeriert, was jedoch für viele Zwecke unwichtig ist. -Mit einem '='-Zeichen hinter dem Zustand kann diesem explizit eine Zahl zugewiesen werden, die dieser repräsentiert. -Dies kann in manchen Fällen sinnvoll sein, da Enums einfach in Integer verwandelt werden können (und anders herum). - -\begin{praxis} - \begin{enumerate} - \item Erweitere \texttt{runden2.cpp} so, dass auch negative Eingaben richtig gerundet werden. Bei Abrunden sollte die Eingabe -1.4 also auf 2 und bei Aufrunden auf 1 gerundet werden. - \item Füge zwei weitere modes hinzu, die jeweils zur Null und von der Null weg runden. - \end{enumerate} -\end{praxis} \ No newline at end of file diff --git a/classes/intro.tex b/classes/intro.tex deleted file mode 100644 index 254a04e..0000000 --- a/classes/intro.tex +++ /dev/null @@ -1,12 +0,0 @@ -\chapter[Objektorientierung]{Einführung in Objektorientierung \& Klassen} -\pagestyle{empty} - -Im nun folgenden Kapitel werden wir lernen einfache Datentypen zu komplexeren Typen in Klassen zusammenzufassen. - -\pagestyle{fancy} -\include{classes/enum} -\include{classes/struct} -\include{classes/operator} -\include{classes/classes} - -\pagestyle{empty} diff --git a/classes/struct.tex b/classes/struct.tex deleted file mode 100644 index 3f15510..0000000 --- a/classes/struct.tex +++ /dev/null @@ -1,53 +0,0 @@ -\lesson{Structs} - -Wir sind bisher dazu in der Lage Variablen von vielen verschiedenen Typen anzulegen. -Wir wollen uns jetzt damit beschäftigen wie wir dreidimensionale Vektoren in \Cpp implementieren können. - -Unsere bisherigen Datentypen sind dafür leider eher ungeeignet. -Wir könnten zwar einen Vektor simulieren indem wir drei \texttt{double} benutzen, allerdings haben wir bisher keine Möglichkeit, eine Funktion zu schreiben, die mehrere Zahlen auf einmal zurück gibt. - -Um Datentypen zu bündeln, gibt es die sogenannten \emph{Structs}. -Diese besitzen verschiedene \emph{Attribute}, zum Beispiel würde ein Vektor drei verschiedene Attribute vom Typ \texttt{double} besitzen. -Das könnte zum Beispiel so aussehen: - -\inputcpp{struct.cpp} - -%Jetzt ist es immer noch umständlich einen neuen Vektor zu initialisieren, da man einzeln $x$, $y$ und $z$ festlegen muss. -%An dieser Stelle wäre eine Möglichkeit, diesen Teil in eine eigene Funktion auszulagern. -%Da das Initialisieren von Attributen eine häufige Aufgabe ist, gibt es sogenannte \emph{Konstruktoren}, die vordefinierte Parameter entgegen nehmen und damit einen bestimmten Struct initialisieren können. -%Das sieht dann zum Beispiel so aus: -% -%\includecpp{konst.cpp} - -\begin{praxis} - \begin{enumerate} - \item Schreibt einen neuen Struct, der ein Datum folgender Art repräsentiert: \texttt{"1 Januar 1971"}. - Dieser Struct sollte also drei Attribute haben: - ein \texttt{int}, um das Jahr zu speichern, - ein \texttt{std::string} für den Monat - und ein weiterer \texttt{int} für den Tag. - - \item Erstellt eine Funktion, die einen \texttt{std::string} als Parameter entgegen nimmt, die Nutzerin mit der Ausgabe des Strings nach einem Datum fragt und dann das Datum mit eurem erstellten Struct zurück gibt. - - \item Fragt mit dieser Funktion die Benutzerin nach ihrem Geburtsdatum. Überprüft, ob ihr am gleichen Tag Geburtstag habt. - Außerdem solltet ihr überprüfen, ob ihr im gleichen Jahr geboren seid. - \end{enumerate} -\end{praxis} -\begin{praxis}[(Quadratsfunktion)] - - \begin{enumerate} - \item Schreibt einen Struct \texttt{Point2D}, der zweidimensionale Punkte - repräsentieren soll. ($a = (x, y) \in \mathbb{R}^2$) - \item In einem früheren Kapitel habt ihr gelernt, wie man Arrays von - Datentypen anlegen kann. Erstellt ein Array aus 100 \texttt{Point2D}s, bei dem die - x-Werte von 0 bis 99 gehen. - \item Berechnet dann für jeden \texttt{x}-Wert das entsprechende \texttt{y}, - indem ihr $y = x^2$ berechnet. - \end{enumerate} -\end{praxis} - -\begin{spiel} - \begin{enumerate} - \item ?? - \end{enumerate} -\end{spiel} \ No newline at end of file diff --git a/files/array.cpp b/files/array.cpp new file mode 100644 index 0000000..e69de29 diff --git a/files/solutions/tictactoe.cpp b/files/solutions/tictactoe.cpp new file mode 100644 index 0000000..2463648 --- /dev/null +++ b/files/solutions/tictactoe.cpp @@ -0,0 +1,124 @@ +#include +#include + +static std::string fts(int feld) { + switch (feld) { + case 0: + return " "; + case 1: + return "X"; + case 2: + return "O"; + default: + return "?"; + } +} + +int frage_feld_nummer(std::array feld){ + int in = -1; + while (true) { + std::cout << "Gib ein Feld ein (0-8): "; + std::cin >> in; + if (in < 0 || in > 8) { + std::cout << "Ungültige Feldnummer!" << std::endl; + continue; + } + if (feld[in] != 0) { + std::cout << "Feld ist besetzt!" << std::endl; + continue; + } + break; + } + return in; +} + +void gebe_feld_aus(std::array feld){ + std::cout << " | | " << std::endl; + std::cout << " " << fts(feld[0]) << " | " << fts(feld[1]) << " | " << fts(feld[2]) << " " << std::endl; + std::cout << " | | " << std::endl; + std::cout << "---+---+---" << std::endl; + std::cout << " | | " << std::endl; + std::cout << " " << fts(feld[3]) << " | " << fts(feld[4]) << " | " << fts(feld[5]) << " " << std::endl; + std::cout << " | | " << std::endl; + std::cout << "---+---+---" << std::endl; + std::cout << " | | " << std::endl; + std::cout << " " << fts(feld[6]) << " | " << fts(feld[7]) << " | " << fts(feld[8]) << " " << std::endl; + std::cout << " | | " << std::endl; +} + +int gewinnerin(std::array feld){ + // Prüfe Reihen und Spalten + for (int i = 0; i < 3; i++) { + int a = feld[3*i] & feld[3*i+1] & feld[3*i+2]; + int b = feld[3*i] | feld[3*i+1] | feld[3*i+2]; + if (a == b && a != 0) { + return feld[3*i]; + } + a = feld[i] & feld[i+3] & feld[i+6]; + b = feld[i] | feld[i+3] | feld[i+6]; + if (a == b && a != 0) { + return feld[i]; + } + } + // Prüfe Diagonale 1 + int a = feld[0] & feld[4] & feld[8]; + int b = feld[0] | feld[4] | feld[8]; + if (a == b && a != 0) { + return feld[0]; + } + + // Prüfe Diagonale 2 + a = feld[2] & feld[4] & feld[6]; + b = feld[2] | feld[4] | feld[6]; + if (a == b && a != 0) { + return feld[2]; + } + + for (int i = 0; i < 9; i++) { + if (feld[i] == 0) { + return 0; + } + } + return 3; +} + + + +int main() { + // Setup +restart: + std::array spielfeld{0}; + int current_player = 1; + int input_player; + + while (true) { + // Input + input_player = frage_feld_nummer(spielfeld); + + // Update + spielfeld[input_player] = current_player; + int gewinner = gewinnerin(spielfeld); + switch (gewinner) { + case 1: + std::cout << "Spieler 1 ist der Gewinner." << std::endl; + goto restart; + + case 2: + std::cout << "Spieler 2 ist der Gewinner." << std::endl; + goto restart; + + case 3: + std::cout << "Das Spiel endet unentschieden." << std::endl; + goto restart; + + default: + current_player = (current_player == 2) ? 1 : 2; + break; + } + + + // Display + gebe_feld_aus(spielfeld); + } + return 0; +} diff --git a/files/solutions/tictactoe_easy.cpp b/files/solutions/tictactoe_easy.cpp new file mode 100644 index 0000000..e44aa77 --- /dev/null +++ b/files/solutions/tictactoe_easy.cpp @@ -0,0 +1,133 @@ +#include +#include + +std::string fts(int feld) { + + if (feld == 0) { + return " "; + } else if (feld == 1) { + return "X"; + } else if (feld == 2) { + return "O"; + } else { + return "?"; + } +} + +int frage_feld_nummer(std::array feld){ + int in = -1; + bool valid = false; + while (!valid) { + std::cout << "Gib ein Feld ein (0-8): "; + std::cin >> in; + if (in < 0 || in > 8) { + std::cout << "Ungültige Feldnummer!" << std::endl; + } + if (feld[in] != 0) { + std::cout << "Feld ist besetzt!" << std::endl; + } + else { + valid = true; // Markiert die Eingabe als gültig wenn keine Fehler aufgetauch sind + } + } + return in; +} + +void gebe_feld_aus(std::array feld){ + std::cout << " | | " << std::endl; + std::cout << " " << fts(feld[0]) << " | " << fts(feld[1]) << " | " << fts(feld[2]) << " " << std::endl; + std::cout << " | | " << std::endl; + std::cout << "---+---+---" << std::endl; + std::cout << " | | " << std::endl; + std::cout << " " << fts(feld[3]) << " | " << fts(feld[4]) << " | " << fts(feld[5]) << " " << std::endl; + std::cout << " | | " << std::endl; + std::cout << "---+---+---" << std::endl; + std::cout << " | | " << std::endl; + std::cout << " " << fts(feld[6]) << " | " << fts(feld[7]) << " | " << fts(feld[8]) << " " << std::endl; + std::cout << " | | " << std::endl; +} + +int gewinnerin(std::array feld){ + // Prüfe Reihen und Spalten + for (int i = 0; i < 3; i++) { + int a = feld[3*i] & feld[3*i+1] & feld[3*i+2]; + int b = feld[3*i] | feld[3*i+1] | feld[3*i+2]; + if (a == b && a != 0) { + return feld[3*i]; + } + a = feld[i] & feld[i+3] & feld[i+6]; + b = feld[i] | feld[i+3] | feld[i+6]; + if (a == b && a != 0) { + return feld[i]; + } + } + // Prüfe Diagonale 1 + int a = feld[0] & feld[4] & feld[8]; + int b = feld[0] | feld[4] | feld[8]; + if (a == b && a != 0) { + return feld[0]; + } + + // Prüfe Diagonale 2 + a = feld[2] & feld[4] & feld[6]; + b = feld[2] | feld[4] | feld[6]; + if (a == b && a != 0) { + return feld[2]; + } + + for (int i = 0; i < 9; i++) { + if (feld[i] == 0) { + return 0; + } + } + return 3; +} + + + +int main() { + // Setup + std::array spielfeld{0}; + int current_player = 1; + int input_player; + + while (true) { + // Input + input_player = frage_feld_nummer(spielfeld); + + // Update + spielfeld[input_player] = current_player; + int gewinner = gewinnerin(spielfeld); + bool reset = false; + + if (gewinner == 1 || gewinner == 2 || gewinner == 3) { // Prüft ob das Spiel beendet ist + reset = true; + if (gewinner == 1) { + std::cout << "Spieler 1 ist der Gewinner." << std::endl; + } else if (gewinner == 2) { + std::cout << "Spieler 2 ist der Gewinner." << std::endl; + } else { + std::cout << "Das Spiel endet unentschieden." << std::endl; + } + } + + if (current_player == 1) { // Wechselt den Spieler + current_player = 2; + } else { + current_player = 1; + } + + // Display + gebe_feld_aus(spielfeld); + + if (reset) // Setzt das Spiel zurück falls es geendet hat + { + current_player = 1; + for (int i = 0; i < 9; i++) { + spielfeld[i] = 0; + } + reset = false; + } + } + return 0; +} diff --git a/files/tictactoe.cpp b/files/tictactoe.cpp index 402916c..02b1bcc 100644 --- a/files/tictactoe.cpp +++ b/files/tictactoe.cpp @@ -1,8 +1,18 @@ #include -#include +#include + +int frage_feld_nummer(std::array feld){ + // Implementiere hier die Abfrage nach dem gespielten Feld // +} + +void gebe_feld_aus(std::array){ + // Hier wird die Funktion implementiert +} + +int gewinnerin(std::array){ + //Hier wird die Funktion implementiert +} -extern int frage_feld_nummer(std::vector feld); -// Fügt hier die anderen Funktionen ein int main() { // Setup diff --git a/files/ttt_closed/frage_feld_nummer.cpp b/files/ttt_closed/frage_feld_nummer.cpp deleted file mode 100644 index 36f39b4..0000000 --- a/files/ttt_closed/frage_feld_nummer.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include -#include - -int frage_feld_nummer(std::vector feld) { - int in = -1; - while (true) { - std::cout << "Gib ein Feld ein (0-8): "; - std::cin >> in; - if (in < 0 || in > 8) { - std::cout << "Ungültige Feldnummer!" << std::endl; - continue; - } - if (feld[in] != 0) { - std::cout << "Feld ist besetzt!" << std::endl; - continue; - } - break; - } - return in; -} diff --git a/files/ttt_closed/gebe_feld_aus.cpp b/files/ttt_closed/gebe_feld_aus.cpp deleted file mode 100644 index 379dafb..0000000 --- a/files/ttt_closed/gebe_feld_aus.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include -#include - -static std::string fts(int feld) { - switch (feld) { - case 0: - return " "; - case 1: - return "X"; - case 2: - return "O"; - default: - return "?"; - } -} - -void gebe_feld_aus(std::vector feld) { - std::cout << " | | " << std::endl; - std::cout << " " << fts(feld[0]) << " | " << fts(feld[1]) << " | " << fts(feld[2]) << " " << std::endl; - std::cout << " | | " << std::endl; - std::cout << "---+---+---" << std::endl; - std::cout << " | | " << std::endl; - std::cout << " " << fts(feld[3]) << " | " << fts(feld[4]) << " | " << fts(feld[5]) << " " << std::endl; - std::cout << " | | " << std::endl; - std::cout << "---+---+---" << std::endl; - std::cout << " | | " << std::endl; - std::cout << " " << fts(feld[6]) << " | " << fts(feld[7]) << " | " << fts(feld[8]) << " " << std::endl; - std::cout << " | | " << std::endl; -} diff --git a/files/ttt_closed/gewinnerin.cpp b/files/ttt_closed/gewinnerin.cpp deleted file mode 100644 index 3f17201..0000000 --- a/files/ttt_closed/gewinnerin.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include -int gewinnerin(std::vector feld) { - // Prüfe reihen und Spalten - for (int i = 0; i < 3; i++) { - int a = feld[3*i] & feld[3*i+1] & feld[3*i+2]; - int b = feld[3*i] | feld[3*i+1] | feld[3*i+2]; - if (a == b && a != 0) { - return feld[3*i]; - } - a = feld[i] & feld[i+3] & feld[i+6]; - b = feld[i] | feld[i+3] | feld[i+6]; - if (a == b && a != 0) { - return feld[i]; - } - } - // Prüfe Diagonale 1 - int a = feld[0] & feld[4] & feld[8]; - int b = feld[0] | feld[4] | feld[8]; - if (a == b && a != 0) { - return feld[0]; - } - - // Prüfe Diagonale 2 - a = feld[2] & feld[4] & feld[6]; - b = feld[2] | feld[4] | feld[6]; - if (a == b && a != 0) { - return feld[2]; - } - - for (int i = 0; i < 9; i++) { - if (feld[i] == 0) { - return 0; - } - } - return 3; -} diff --git a/files/ttt_closed/tictactoe.cpp b/files/ttt_closed/tictactoe.cpp deleted file mode 100644 index 16a6bad..0000000 --- a/files/ttt_closed/tictactoe.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// This is awefull. But we need a single .cpp-file and this way we can change -// the implementation at all points at the same time -#include "frage_feld_nummer.cpp" -#include "gebe_feld_aus.cpp" -#include "gewinnerin.cpp" diff --git a/basics/arith.tex b/lektionen/arithmetics.tex similarity index 100% rename from basics/arith.tex rename to lektionen/arithmetics.tex diff --git a/lektionen/arrays_vectors.tex b/lektionen/arrays_vectors.tex new file mode 100644 index 0000000..c742551 --- /dev/null +++ b/lektionen/arrays_vectors.tex @@ -0,0 +1,166 @@ +\lesson{\texttt{C}-Arrays} + +Als nächstes wichtiges Konzept in \Cpp werden wir uns \emph{Arrays} anschauen. +Arrays sind eine Möglichkeit, mehrere Elemente des gleichen Typs zusammen zu +fassen. Statt also einer Stelle im Speicher, an der ein \texttt{int} liegt, +habt ihr einen ganzen Speicherbereich, in dem 100 (oder eine beliebige andere +Anzahl an) \texttt{int}s liegen. + +Die Elemente in einem Array sind durchnummeriert, man nennt die Nummer eines +Arrayelements seinen \emph{Index}. Das erste Element hat den Index 0, das +zweite den Index 1 und das 100te hat den Index 99 -- Vorsicht also, der höchste +Index in einem Array mit 100 Elementen ist 99, nicht 100! Um ein Array zu +definieren, schreibt ihr hinter seinen Namen eine eckige Klammer auf, die +Anzahl an Elementen, die es enthalten soll, und eine eckige Klammer zu. Auf ein +bestimmtes Arrayelement zuzugreifen könnt ihr tun, indem ihr seinen Index in +eckigen Klammern hinter den Namen schreibt. Folgendes Programm macht +hoffentlich die Syntax klar: +\inputcpp{array.cpp} % ToDo: Add this file + +Es gibt einige Dinge, zu beachnten, wenn ihr mit Arrays arbeitet. Das +wichtigste ist oben schon genannt -- sich davon verwirren zu lassen, dass +Indizes bei 0 anfangen und aus Versehen über das Array hinaus schreiben oder +lesen ist ein so häufiger Fehler, dass er seinen eigenen Namen bekommen hat: +„Off-by-one error“. Wichtig ist, dass der Compiler diesen Zugriff nicht +verhindern wird! Das ist von daher eine sehr fiese Sache, als dass dieser +Fehler auch beim Ausführen nicht immer Probleme machen wird -- aber manchmal +lässt er auch euer Programm spontan abstürzen in einem so genannten +\emph{segmentation fault}. + +Eine Limitation von Arrays, die ihr beachten solltet, ist, dass bereits zur +Compilezeit fest stehen muss, wie viele Elemente sie enthalten sollen. Ihr +könnt also z.B. nicht die Nutzerin fragen, wie viele Elemente in das Array +passen soll, denn dies würde erst zur Laufzeit feststehen (wir werden später +noch Wege um diese Limitation kennen lernen). + +Ihr könnt auch Arrays von Arrays (so genannte zweidimensionale Arrays) +erstellen, indem ihr zweimal in eckigen Klammern die Größe des Arrays +hinschreibt. Die erste Größe gibt dann die Anzahl der Zeilen an, die zweite die +Anzahl der Spalten. Auch beim Zugriff auf Arrayelemente müsst ihr dann zwei +Indizes angeben. Wir werden dies später noch nutzen, hier sei erst einmal nur +die generelle Möglichkeit genannt. + +\textbf{Praxis:} +Wir wollen die Seite \url{http://www.ich-kann-mich-nicht-entscheiden.de/} +nachmachen und eine Entscheidungshilfe programmieren, die aus mehreren von der +Nutzerin gegebenen Möglichkeiten eine per Zufall auswählt. + +\begin{enumerate} + \item Schreibt zunächst ein Programm, welches ein Array aus 10 Strings + erstellt und die Nutzerin 10 mal nach einer Antwortmöglichkeit fragt + und die gegebenen Antworten nacheinander in das Array schreibt. + \item Fügt nun die Möglichkeit zu, weniger Antworten anzugeben. Dazu könnt + ihr zum Beispiel zuerst fragen, wie viele Antwortmöglichkeiten es geben + soll und dann so oft fragen (und natürlich einen Fehler ausgeben, wenn + es mehr als 10 Antworten geben soll). + \item Ihr könnt dann (so wie in dem Programm oben) eine Zufallszahl + erzeugen. Um sicher zu gehen, dass sie nicht zu groß wird, könnt ihr + den Rest bei Teilung durch Anzahl der eingegebenen Antworten nehmen + (sind z.B. 7 Antworten angegeben und die Zufallszahl ist 25778, so wäre + der resultierende Index \texttt{25778 \% 7 == 4}). Gebt dann die + Antwortmöglichkeit aus, die dem zufallsgeneriertem Index + entspricht. +\end{enumerate} + +Sollte euer Programm einmal nicht korrekt kompilieren, denkt daran die +Fehlermeldung sorgfältig zu lesen, damit sie euch Aufschluss über die +Fehlerursache gibt. Sollte euer Programm zwar kompilieren, sich dann aber +komisch verhalten, denkt daran, den debugger zu benutzen und es Schritt für +Schritt durchzugehen, um die Fehlerquelle zu finden. Solltet ihr trotz alledem +nicht weiter kommen, oder nicht wissen, was von euch erwartet wird, fragt einen +von uns. + +\textbf{Spiel:} +\begin{enumerate} + \item Schreibt ein Progamm, welches ein Array beliebiger Größe erstellt und + dann auf einen Index weit ausserhalb des erlaubten Bereichs schreibt. + Was beobachtet ihr?\footnote{Es wird natürlich Quark sein was dabei + rauskommt, es geht hier haupsächlich darum das ihr seht was für + einen Fehler das gibt} + \item Implementiert das \emph{Sieb des Eratosthenes} + \footnote{\url{https://de.wikipedia.org/wiki/Sieb_des_Eratosthenes}}, + wenn ihr noch nicht ausgelastet seid. + Denkt daran, es initial zu befüllen und denkt euch eine clevere + Möglichkeit aus, das „Streichen“ zu realisieren. +\end{enumerate} + + +\lesson{Vektor} + +Als nächstes wichtiges Konzept in \Cpp werden wir uns \emph{Vektoren} anschauen. +Vektoren sind eine Möglichkeit, mehrere Elemente des gleichen Typs zusammen zu fassen. +Statt also einer Stelle im Speicher, an der ein \texttt{int} liegt, habt ihr einen ganzen Speicherbereich, in dem 100 (oder eine beliebige andere Anzahl an) \texttt{int}s liegen. + +Die Elemente in einem Vektor sind durchnummeriert, man nennt die Nummer eines Vektorelements seinen \emph{Index}. +Das erste Element hat den Index 0, das zweite den Index 1 und das 100te hat den Index 99 -- Vorsicht also, der höchste Index in einem Vektor mit 100 Elementen ist 99, nicht 100! +Um einen Vektor zu definieren, schreibt ihr: +\begin{center} + \cppinline{std::vector<}\emph{Datentyp}\cppinline{> einvektor;} +\end{center} +um den Datentypen schreibt ihr also noch \cppinline{std::vector<}\dots\cppinline{>}. +Um ein Element am Ende einzufügen gibt es +\begin{center} + \cppinline{einvektor.push_back(}\emph{Element}\cppinline{);} +\end{center} +und auf ein bestimmtes Vektorelement zugreifen könnt ihr indem ihr seinen Index in eckigen Klammern hinter den Namen schreibt. +\begin{center} + \cppinline{einvektor[}\emph{Index}\cppinline{]} +\end{center} +Wenn ihr die Größe eines Vektors wissen wollt könnt ihr +\begin{center} + \cppinline{einvektor.size()} +\end{center} +verwenden. + +Folgendes Programm macht hoffentlich die Syntax klar: + +\inputcpp{vector.cpp} + +Es gibt einige Dinge, zu beachten, wenn ihr mit Vektoren arbeitet. +Das wichtigste ist oben schon genannt -- lasst euch nicht davon verwirren, dass Indizes bei 0 anfangen. +Aus Versehen über den Vektor hinaus zu schreiben oder zu lesen ist ein so häufiger Fehler, dass er seinen eigenen Namen bekommen hat: \emph{Off-by-one} error. +Wichtig ist, dass der Compiler diesen Zugriff nicht verhindern wird! +Das ist von daher eine sehr fiese Sache, als dass dieser Fehler auch beim Ausführen nicht immer Probleme machen wird -- aber manchmal lässt er auch euer Programm spontan abstürzen in einem so genannten \emph{segmentation fault}. + +\begin{praxis} + + Wir wollen die Seite \url{http://www.ich-kann-mich-nicht-entscheiden.de/} nachmachen und eine Entscheidungshilfe programmieren, die aus mehreren von der Nutzerin gegebenen Möglichkeiten eine per Zufall auswählt. + + \begin{enumerate} + \item + Schreibt zunächst ein Programm, welches einen Vektor aus 10 Strings erstellt und die Nutzerin 10 mal nach einer Antwortmöglichkeit fragt und die gegebenen Antworten nacheinander in den Vektor schreibt. + \item + Fügt nun die Möglichkeit zu, weniger Antworten anzugeben. + Dazu könnt ihr zum Beispiel zuerst fragen, wie viele Antwortmöglichkeiten es geben soll und dann so oft fragen. + \item + Ihr könnt dann (so wie in dem Programm oben) eine Zufallszahl erzeugen. + Um sicher zu gehen, dass sie nicht zu groß wird, könnt ihr den Rest bei Teilung durch Anzahl der eingegebenen Antworten nehmen (sind z.B. 7 Antworten angegeben und die Zufallszahl ist 25778, so wäre der resultierende Index \texttt{25778 \% 7 == 4}). + Gebt dann die Antwortmöglichkeit aus, die dem zufallsgeneriertem Index entspricht. + \end{enumerate} +\end{praxis} + +Sollte euer Programm einmal nicht korrekt kompilieren, denkt daran die Fehlermeldung sorgfältig zu lesen, damit sie euch Aufschluss über die Fehlerursache gibt.\\ +Sollte euer Programm zwar kompilieren, sich dann aber komisch verhalten, denkt daran, den Debugger zu benutzen und es Schritt für Schritt durchzugehen, um die Fehlerquelle zu finden. Solltet ihr trotz alledem nicht weiter kommen, oder nicht wissen, was von euch erwartet wird, fragt einen von uns. + + +\begin{spiel} +\begin{enumerate} + \item + Schreibt ein Progamm, welches einen Vektor mit einer beliebigen Anzahl an Elementen befüllt und dann auf einen Index weit über der tatsächlichen Größe schreibt. + Was beobachtet ihr?\footnote{Es wird natürlich Quark sein was dabei rauskommt, es geht hier haupsächlich darum das ihr seht was für einen Fehler das gibt} + \item + Überlegt euch wie ihr verhindern könnt, dass über den Rand des Vektors hinaus geschrieben oder gelesen wird. + \item + Implementiert das \emph{Sieb des Eratosthenes}\footnote{\url{https://de.wikipedia.org/wiki/Sieb_des_Eratosthenes}}, wenn ihr noch nicht ausgelastet seid. + Denkt daran, es initial zu befüllen und denkt euch eine clevere Möglichkeit aus, das „Streichen“ zu realisieren. +\end{enumerate} +\end{spiel} + +\textbf{Quiz 15}\\ +\textit{Welche Aussagen über Vektoren sind falsch?} +\begin{enumerate}[label=\alph*)] + \item Vektoren haben immer die Größe 3 + \item Vektoren können nur mit Elementen eines einzigen Datentyps befüllt werden + \item Der Index startet bei 0 + \item Der letzte Index ist immer die Größe - 1 +\end{enumerate} diff --git a/basics/compiling.tex b/lektionen/compiling.tex similarity index 78% rename from basics/compiling.tex rename to lektionen/compiling.tex index dbf198b..9a8577b 100644 --- a/basics/compiling.tex +++ b/lektionen/compiling.tex @@ -1,12 +1,10 @@ \lesson{Preprocessing, Compiler, Assembler, Linker} -In der letzten Lektion klang es bereits an -- was der Befehl \texttt{g++} -eigentlich tut, ist mehr, als nur Kompilieren im strengen Sinne des Wortes. Wir -wollen jetzt kurz erkunden, welche anderen Schritte in den Prozess vom -Quellcode in die ausführbare Datei notwendig sind und wie sie geschehen. Das -ist im Alltag nicht sehr wichtig, kann uns aber helfen, einige Fehlermeldungen -besser zu verstehen. Von daher müsst ihr auch nicht alles hier beschriebene -vollständig verstehen. +In der letzten Lektion habt ihr bereits das erste mal ein Programm kompiliert, +d.h. ihr habt eine für Menschen lesbare Datei in eine für Computer lesbare Datei +übersetzt. Jetzt wollen wir uns etwas genauer anschauen was dabei eigentlich passiert. +Ihr müsst dabei jetzt nicht jedes Detail vestehen, aber es ist praktisch zu +wissen, wie der Compile Vorgang funktioniert um manche Fehlermeldungen zu verstehen. In Lektion 1 haben wir vereinfacht dargestellt, dass der Compiler eine Quelltextdatei mit der Endung \texttt{.cpp} nimmt und daraus direkt eine @@ -14,9 +12,15 @@ durchgeführt werden, aber zu trennen sind, sind das \emph{Preprocessing}, das \emph{Kompilieren}, das \emph{Assemblieren} und das \emph{Linken}. -Beim Preprocessing werden alle \texttt{\#include}-Anweisungen aufgelöst und so etwas wie Makros ersetzt. Das ist der erste Schritt, der passiert, wenn wir \texttt{g++} aufrufen. Das Ergebnis des Preprocessings ist ein \Cpp-Programm, das nur noch die \Cpp-Features enthält, die wir auch wirklich benutzen. Das ist der Grund, warum wir in den bisherigen Lektionen immer \texttt{g++ -o helloworld helloworld.cpp} benutzt haben, obwohl wir in \texttt{helloworld.cpp} auch \texttt{\#include } stehen haben -- der Compiler hat das schon für uns erledigt. +Beim Preprocessing werden alle \texttt{\#include}-Anweisungen aufgelöst. +Das ist der erste Schritt, der passiert, wenn wir \texttt{g++} +aufrufen. Das Ergebnis des Preprocessings ist ein erweitertes\Cpp-Programm, das nur noch die +\Cpp-Features enthält, die wir auch wirklich benutzen. Das ist der Grund, warum wir +in den bisherigen Lektionen immer \texttt{g++ -o helloworld helloworld.cpp} benutzt haben, +obwohl wir in \texttt{helloworld.cpp} auch \texttt{\#include } stehen haben +-- der Compiler hat das schon für uns erledigt. -Das Kompilieren übersetzt unseren \Cpp-Code in eine Zwischenform, so genannten +Das Kompilieren übersetzt unseren erweiterten \Cpp-Code in eine Zwischenform, so genannten \emph{Assembler}. In Lektion 1 haben wir den Maschinencode angesprochen, in der Befehle und Parameter an Befehle in 1en und 0en dargestellt werden. Assembler ist quasi die nächst höhere Evolutionsstufe -- statt die Befehle binär zu @@ -52,15 +56,15 @@ Objectfiles eine \texttt{main}-Funktion existiert, wird diese als Eintrittspunkt für das Programm genommen, sonst gibt es einen \emph{Linkerfehler}. Ein Linkerfehler tritt auch auf, wenn wir versuchen, eine -Funktion zu verwenden, die es nicht gibt (z.B. indem wir sie mittels -\texttt{extern} deklarieren, ohne später das relevante Objectfile mit -anzugeben). Linkerfehler deuten also darauf hin, dass wir vergessen haben, alle +Funktion zu verwenden, die es nicht gibt (z.B. indem wir Funktionen aus einem +Headerfile benutzen ohne das Header-File mit \texttt{\#include} auch tatsächlich einzubinden). +Linkerfehler deuten also darauf hin, dass wir vergessen haben, alle relevanten Dateien auf der Kommandozeile anzugeben, oder dass eine \texttt{main}-Funktion fehlt, oder dass wir in mehren Dateien eine Funktion gleichen Namens haben, oder\dots -Um das Diagramm aus der ersten Lektion zu ergänzen, dies ist der Weg, den euer -Programm durch die verschiedenen Phasen geht: +Wenn ihr das Programm aus der letzten Lektion kompiliert passiert im Prinzip also +folgendes: \begin{tikzpicture} \tikzstyle{block} = [ shape=rectangle, rounded corners = 0.1cm, draw=black, inner xsep=0.5cm, inner ysep = 0.3cm ]; @@ -84,13 +88,8 @@ unserer input-Datei zu der gewünschten zu kommen automatisch aus, wenn wir also \texttt{g++ -o helloworld helloworld.cpp} eingeben, dann weiß der Compiler, dass wir eine ausführbare Datei wünschen (da wir weder \texttt{-c} noch -\texttt{-S} angegeben haben) und dass er dafür kompilieren, assemblieren und -linken muss (da wir ihm eine \texttt{.cpp} Datei gegeben haben). Genauso konnte -er in der vorigen Lektion raten, dass \texttt{g++ -o tictactoe tictactoe.cpp - tictactoe.o} heißt, dass wir eine ausführbare Datei wollen, die aus einem -kompilierten und assemblierten \texttt{tictactoe.cpp} zusammen gelinkt mit -\texttt{tictactoe.o} bestehen soll. - +\texttt{-S} angegeben haben) und dass er dafür preprocessen, kompilieren, assemblieren und +linken muss (da wir ihm eine \texttt{.cpp} Datei gegeben haben). \begin{praxis} \begin{enumerate} \item \texttt{assemble.cpp} enthält ein kleines (ziemlich nutzloses) @@ -119,4 +118,4 @@ \end{enumerate} \inputcpp{assemble.cpp} -\end{praxis} \ No newline at end of file +\end{praxis} diff --git a/basics/kontrollfluss.tex b/lektionen/control_flow.tex similarity index 100% rename from basics/kontrollfluss.tex rename to lektionen/control_flow.tex diff --git a/basics/gdb.tex b/lektionen/debbugging.tex similarity index 100% rename from basics/gdb.tex rename to lektionen/debbugging.tex diff --git a/eigene_computer/intro.tex b/lektionen/eigener_computer/intro.tex similarity index 74% rename from eigene_computer/intro.tex rename to lektionen/eigener_computer/intro.tex index c420225..72334af 100644 --- a/eigene_computer/intro.tex +++ b/lektionen/eigener_computer/intro.tex @@ -5,6 +5,6 @@ \chapter{Vorbereitung eigener Computer} Wir werden in diesem Fall den proprietären Editor „Visual Studio Code“ verwenden, welcher \href{https://code.visualstudio.com/Download}{hier} heruntergeladen werden kann.\\ \pagestyle{fancy} -\input{eigene_computer/windows.tex} -\input{eigene_computer/macos.tex} -\input{eigene_computer/linux.tex} \ No newline at end of file +\input{lektionen/eigener_computer/linux} +\input{lektionen/eigener_computer/windows} +\input{lektionen/eigener_computer/macos} diff --git a/eigene_computer/linux.tex b/lektionen/eigener_computer/linux.tex similarity index 100% rename from eigene_computer/linux.tex rename to lektionen/eigener_computer/linux.tex diff --git a/eigene_computer/macos.tex b/lektionen/eigener_computer/macos.tex similarity index 100% rename from eigene_computer/macos.tex rename to lektionen/eigener_computer/macos.tex diff --git a/eigene_computer/windows.tex b/lektionen/eigener_computer/windows.tex similarity index 100% rename from eigene_computer/windows.tex rename to lektionen/eigener_computer/windows.tex diff --git a/basics/fehler.tex b/lektionen/errors_warnings.tex similarity index 100% rename from basics/fehler.tex rename to lektionen/errors_warnings.tex diff --git a/lektionen/exercises/intro.tex b/lektionen/exercises/intro.tex new file mode 100644 index 0000000..4029f80 --- /dev/null +++ b/lektionen/exercises/intro.tex @@ -0,0 +1,5 @@ +\chapter{Zusätzliche Übungen} +\pagestyle{empty} +Dieses Kapitel dient als Aufgabenpool für zusätzliche Übungen, die ihr bearbeiten könnt, um euer Wissen zu festigen. + +\pagestyle{fancy} diff --git a/basics/funktionen.tex b/lektionen/functions.tex similarity index 94% rename from basics/funktionen.tex rename to lektionen/functions.tex index edee670..77071e3 100644 --- a/basics/funktionen.tex +++ b/lektionen/functions.tex @@ -9,13 +9,13 @@ Die Kombination von Parametertypen und Rückgabetyp bildet die Signatur einer Funktion. Parameter sind Werte, die der Funktion übergeben werden, zum Beispiel das $x$ in $f(x)$. Für eine Funktion \cppinline{my_func}, die $x^n$ berechnen soll, könnte eine Signatur so aussehen: -\[ - \smashoperator{\mathop{\underbrace{\text{\cppinline{double}}}}_{\text{Rückgabetyp}}}\quad - \smashoperator{\mathop{\overbrace{\text{\cppinline{my_func}}}}^{\text{Name}}} - (\smashoperator{\mathop{\underbrace{\text{\cppinline{double x}}}}_{\text{Parameter 1}}},\ - \smashoperator{\mathop{\overbrace{\text{\cppinline{int n}}}^{\text{Parameter 2}}}}) -\] -%sorry etwas hässlich +%\[ +% \smashoperator{\mathop{\underbrace{\text{\cppinline{double}}}}_{\text{Rückgabetyp}}}\quad +% \smashoperator{\mathop{\overbrace{\text{\cppinline{my_func}}}}^{\text{Name}}} +% (\smashoperator{\mathop{\underbrace{\text{\cppinline{double x}}}}_{\text{Parameter 1}}},\ +% \smashoperator{\mathop{\overbrace{\text{\cppinline{int n}}}^{\text{Parameter 2}}}}) +%\] +% This structure currently causes the workflow to crash. It will need to be addressed in the future. \begin{itemize} \item Rückgabetyp: Bestimmt welchen Datentyp die Rückgabe der Funktion hat diff --git a/basics/input.tex b/lektionen/input.tex similarity index 100% rename from basics/input.tex rename to lektionen/input.tex diff --git a/basics/hello_world.tex b/lektionen/input_output_hello_world.tex similarity index 72% rename from basics/hello_world.tex rename to lektionen/input_output_hello_world.tex index ef6c74c..b5c93b5 100644 --- a/basics/hello_world.tex +++ b/lektionen/input_output_hello_world.tex @@ -129,3 +129,60 @@ \item Das Programm tut garnichts mehr \item Das Programm gibt trotzdem \texttt{Hello world} aus \end{enumerate} + +\lesson{Input und Output} + +Nachdem wir ein bisschen Vertrauen in die shell entwickelt haben und zumindest +bereits unser erstes Programm kompiliert, wollen wir nun etwas spannendere +Dinge tun. Nach wie vor müsst ihr nicht jede Zeile eures Programmes verstehen. +Sollte euch bei einer bestimmten Zeile trotzdem interessieren, was genau sie +tut, versucht doch eventuell sie zu entfernen, das Programm zu kompilieren und +schaut, was sich ändert. + +Wir wollen uns nun mit grundlegendem input und output vertraut machen, denn +erst wenn euer Programm mit einer Benutzerin interagiert, wird es wirklich +nützlich. Wir haben in der ersten Lektion bereits \texttt{cout} (für +\emph{console out}) kennengelernt, um Dinge auszugeben. Nun nutzen wir +\texttt{cin}, um Eingaben des Benutzers entgegen zu nehmen. Jedes Programm +unter Linux (und übrigens auch Mac OS oder Windows) kann auf diese Weise +Eingaben von der Nutzerin entgegen nehmen und Ausgaben liefern. Das ist auch +der Grund, warum die Konsole so wichtig ist und es viele Dinge gibt, die nur +mittels einer Konsole gelöst werden können: Während es viele Stunden dauert, +ein grafisches Interface zu programmieren, über die man mit dem Programm mit +der Maus kommunizieren kann, kann praktisch jeder ein textbasiertes +Konsoleninterface schreiben. Linux ist ein Ökosystem mit einer gewaltigen +Anzahl tools für jeden denkbaren Zweck und bei den meisten haben die Autorinnen +sich nicht die Mühe gemacht, extra eine grafische Oberfläche zu entwickeln. + +Nun aber direkt zur Praxis: + +\begin{praxis} + \begin{enumerate} + \item Öffnet die Datei \texttt{vorkurs/lektion03/helloyou.cpp} in eurem Texteditor + \item Öffnet ein Terminal und wechselt in das Verzeichnis \texttt{vorkurs/lektion03} + \item Kompiliert im Terminal die Datei (\texttt{g++ -o helloyou + helloyou.cpp}) und führt sie aus (\texttt{./helloyou}) + \item Versucht verschiedene Eingaben an das Programm und beobachtet, was passiert + \end{enumerate} + + \inputcpp{helloyou.cpp} +\end{praxis} + +\begin{spiel} +\begin{enumerate} + \item Versucht, zu verstehen, was die einzelnen Teile des Programms tun. An + welcher Stelle erfolgt die Eingabe? Was passiert dann damit? + \item Erweitert das Programm um eigene Fragen und Ausgaben. Vergesst nicht, + dass ihr das Programm nach jeder Änderung neu kompilieren und testen + müsst. +\end{enumerate} +\end{spiel} + +\textbf{Quiz 3}\\ +\textit{Was passiert, wenn \texttt{std::cin >> eingabe;} vor \texttt{std::string eingabe;} steht?} +\begin{enumerate}[label=\alph*)] + \item Das Programm funktioniert ganz normal + \item Es wird \texttt{eingabe} ausgegeben + \item Es wird \texttt{Hello} ausgegeben + \item Das Programm kann nicht kompiliert werden +\end{enumerate} diff --git a/basics/intro.tex b/lektionen/intro.tex similarity index 67% rename from basics/intro.tex rename to lektionen/intro.tex index 664f437..5126872 100644 --- a/basics/intro.tex +++ b/lektionen/intro.tex @@ -10,31 +10,27 @@ \chapter{Die Basics} wir Vektoren kennenlernen und unser erstes nützliches Progamm schreiben. \pagestyle{fancy} -\input{basics/hello_world} -\input{basics/konsole} -\input{basics/input} -\input{basics/fehler} -\input{basics/variablen} -\input{basics/manpages} -\input{basics/arith} -\input{basics/kontrollfluss} -\input{basics/rechte} -\input{basics/schleifen} -\input{basics/gdb} -\input{basics/style} -\input{basics/funktionen} -\input{basics/stdbib} -\input{basics/vektoren} -\input{basics/warning} -\input{basics/tictactoe1} -\input{basics/compiling.tex} -\input{basics/tictactoe2} +\input{lektionen/eigener_computer/intro} +\input{lektionen/unix_shell} +\input{lektionen/input_output_hello_world} +\input{lektionen/compiling} +\input{lektionen/variables_datatypes} +\input{lektionen/arithmetics} +\input{lektionen/control_flow} +\input{lektionen/loops} +\input{lektionen/debbugging} +\input{lektionen/functions} +\input{lektionen/stdlib} +\input{lektionen/arrays_vectors} +\input{lektionen/recursion} +\input{lektionen/errors_warnings} +\input{lektionen/tictactoe} +\input{lektionen/exercises/intro} %ToDo, also needs to bed added \clearpage \pagestyle{empty} -Ihr habt hiermit das erste Kapitel unseres -Programmiervorkurses abgeschlossen. Wir hoffen, ihr hattet dabei Spaß und habt +Ihr habt hiermit unseren Programmiervorkurses abgeschlossen. Wir hoffen, ihr hattet dabei Spaß und habt genug gelernt, um euch gut auf eure erste Programmiervorlesung vorbereitet zu fühlen. diff --git a/basics/loesungen.tex b/lektionen/loesungen.tex similarity index 100% rename from basics/loesungen.tex rename to lektionen/loesungen.tex diff --git a/basics/schleifen.tex b/lektionen/loops.tex similarity index 100% rename from basics/schleifen.tex rename to lektionen/loops.tex diff --git a/basics/manpages.tex b/lektionen/manpages.tex similarity index 100% rename from basics/manpages.tex rename to lektionen/manpages.tex diff --git a/basics/rechte.tex b/lektionen/rechte.tex similarity index 100% rename from basics/rechte.tex rename to lektionen/rechte.tex diff --git a/lektionen/recursion.tex b/lektionen/recursion.tex new file mode 100644 index 0000000..e69de29 diff --git a/basics/stdbib.tex b/lektionen/stdlib.tex similarity index 100% rename from basics/stdbib.tex rename to lektionen/stdlib.tex diff --git a/basics/tictactoe1.tex b/lektionen/tictactoe.tex similarity index 64% rename from basics/tictactoe1.tex rename to lektionen/tictactoe.tex index 8cd96ba..6dddaf1 100644 --- a/basics/tictactoe1.tex +++ b/lektionen/tictactoe.tex @@ -1,29 +1,20 @@ -\lesson{Tic Tac Toe - Teil 1} +\lesson{Tic Tac Toe} -Nachdem wir jetzt lange dröge und unspannende Lektionen und Beispiele hatten, wollen wir uns als Ende von -Kapitel 1 einer ein wenig spannenderen Aufgabe widmen -- wir wollen ein +Nachdem wir jetzt lange dröge und unspannende Lektionen und Beispiele hatten, wollen wir uns jetzt einer +ein wenig spannenderen Aufgabe widmen -- wir wollen ein einfaches Spiel programmieren. Wir haben dazu Tic Tac Toe ausgewählt, da es relativ überschaubare Spiellogik besitzt. Ein- und Ausgabe, werden wir über die Konsole machen. -In \texttt{vorkurs/lektion17} findet ihr eine Datei \texttt{tictactoe.o}. Diese -könnt ihr nicht in eurem Editor öffnen -- sie enthält von uns bereitgestellte, -bereits vorkompilierte Funktionen, die ihr nutzen könnt, um einen Anfang zu -haben. Wir werden sie später Stück für Stück ersetzen. +In \texttt{vorkurs/lektion14} findet ihr eine Datei \texttt{tictactoe.cpp}. +\inputcpp{tictactoe.cpp} -Um die Funktionen zu nutzen, müsst ihr zwei Dinge tun: Ihr müsst sie einerseits -in eurem Sourcecode \emph{deklarieren}, andererseits müsst ihr sie beim -Kompilieren mit \emph{linken}. +Das Spielfeld stellen wir intern als Array mit 9 Integern dar. Der Wert des Integers beschreibt wem das Feld gehört. +Wenn das Feld Spieler 1 gehört, steht dort eine 1, gehört es Spieler 2 steht dort eine 2 und gehört es noch niemandem, +dann steht da eine 0. -Die Deklaration erfolgt ganz ähnlich, wie ihr auch vorgehen würdet, wenn ihr -die Funktion selbst schreiben würdet: Ihr schreibt Rückgabetyp, Namen und -Parameter der Funktion auf. Statt des Funktionenkörpers in geschweiften -Klammern, beendet ihr die Zeile mit einem Semikolon. Da wir die Funktion aus -einer anderen Datei laden wollen, müssen wir noch ein \texttt{extern} -voranstellen. In \texttt{tictactoe.cpp} ist dies am Beispiel von -\texttt{frage\_feld\_nummer} vorgemacht. +Wir strukturieren die Spieleimplementierung, indem wir drei Hilfsfunktionen einführen. Diese übernehmen jeweils spezifische Aufgaben innerhalb der Spiellogik. -\texttt{tictactoe.o} definiert euch insgesamt folgende Funktionen: \begin{description} \item[frage\_feld\_nummer] Nimmt einen Vektor mit 9 \texttt{int}s entgegen und gibt einen \texttt{int} zurück. @@ -45,18 +36,30 @@ Sollte das Spiel unentschieden ausgegangen sein, wird eine 3 zurück gegeben. \end{description} -Der zweite Teil, den ihr zur Benutzung der Funktionen braucht ist das Linken (was genau das bedeutet, wird später noch erklärt). -Dies ist fürs Erste sehr einfach: Ihr gebt einfach dem \texttt{g++} Befehl zusätzlich zu eurer \texttt{.cpp} Datei noch \texttt{tictactoe.o} als zusätzliche Inputdatei an. -\inputcpp{tictactoe.cpp} \begin{praxis} \begin{enumerate} - \item - Ergänzt \texttt{tictactoe.cpp} um Deklarationen für die anderen beschriebenen Funktionen aus \texttt{tictactoe.o}. - Einen Vektor als Parameter könnt ihr in genau der gleichen Notation angeben, wie ihr es euch in einer Funktion als Variable definieren würdet. - \item - Das Grundgerüst eines Spiels ist die \emph{input-update-display}-loop. + \item Implementiert \texttt{frage\_feld\_nummer}. Ihr solltet darauf + achten, dass ihr in dieser Funktion auch testet, ob ein gültiges + Feld eingegeben wurde und ob das angegebene Feld leer ist. + + \item Implementiert \texttt{gebe\_feld\_aus}. Ihr könnt euch selbst + aussuchen, wie ihr die Ausgabe gestalten wollt. + Wikipedia\footnote{\url{http://en.wikipedia.org/wiki/Box-drawing_character}} + kann euch z.B. helfen, ein schöneres Feld auszugeben. Fangt am Besten + mit einer einfachen Ausgabe an und macht sie dann immer „fancier“. + + \item Implementiert \texttt{gewinnerin}. Denkt daran, dass ihr alle + Möglichkeiten testet, die mit einem Gewinnen enden - also 3 + Möglichkeiten, eine Reihe zu bilden, 3 Möglichkeiten, eine Spalte zu + bilden und 2 Möglichkeiten für Diagonalen. Überlegt euch zunächst, wie + ihr zwischen Feldnummer (0-8) und Reihen- bzw. Spaltennummer hin- und + herrechnen könnt. Beachtet auch, dass es ein Unentschieden gibt, wenn + alle Felder belegt sind, aber keine von beiden Spielerinnen gewonnen + hat. + \item + Das Grundgerüst des Spiels ist die \emph{input-update-display}-loop. Dies ist eine Endlosschleife, in der zunächst der \emph{input} der Spielerin abgefragt wird. Anschließend wird der interne Spielzustand aktualisiert (\emph{update}). Zuletzt wird der neue Spielzustand angezeigt (\emph{display}). diff --git a/basics/konsole.tex b/lektionen/unix_shell.tex similarity index 100% rename from basics/konsole.tex rename to lektionen/unix_shell.tex diff --git a/basics/variablen.tex b/lektionen/variables_datatypes.tex similarity index 100% rename from basics/variablen.tex rename to lektionen/variables_datatypes.tex diff --git a/basics/vektoren.tex b/lektionen/vectors.tex similarity index 100% rename from basics/vektoren.tex rename to lektionen/vectors.tex diff --git a/basics/warning.tex b/lektionen/warning.tex similarity index 100% rename from basics/warning.tex rename to lektionen/warning.tex diff --git a/vorkurs.tex b/vorkurs.tex index 00b08bc..ccd96a7 100644 --- a/vorkurs.tex +++ b/vorkurs.tex @@ -165,8 +165,7 @@ \chapter*{Vorwort} \tableofcontents -\input{eigene_computer/intro.tex} -\input{basics/intro.tex} -\input{classes/intro.tex} +\input{lektionen/intro.tex} +\input{appendix/intro.tex} \end{document}