Projekt: ConsoleGames
DEADLINE: (siehe Details zur Abgabe weiter unten)
- Freitag 30. Januar 2026, @23.59 (Freitag von Ferien)
- Mündliche Prüfung am Dienstag 3. Feb. 2026
Ziele:
- Zusammen eine Sammlung von Singleplayer-Konsolengames erstellen.
- Alle steuern alleine ein Game bei,
- … wobei das Framework vorgegeben ist.
- Grundideen der objektorientierten Programmierung (OOP) verstehen.
- Wissen, welche Variablen/Funktionen/Methoden private und welche public sein sollen.
- Game zuerst sauber modellieren, erst dann ausprogrammieren.
- Paradigma von Model vs. View anwenden.
- Ansprechendes GUI u.a. mit Farbe in Konsole erstellen.
Bevor wir aber mit dem eigentlichen Game anfangen, bereiten wir uns mit einigen Aufträgen darauf vor.
Übersicht
Das Ziel ist, in der Klasse eine Konsolen-Game-Sammlung zu erstellen, wobei ihr alle ein Game beisteuert. Das Framework, in welches euer Game dann eingebunden wird, wird von den Lehrpersonen vorgegeben. In diesem Framework kann man dann u.A. das Game auswählen, Spielstände speichern und Highscores einsehen.
Das Game wird bewertet und es gibt eine mündliche Prüfung dazu. Beides zusammen gibt die zweite Note in diesem Semester.
Slides
Framework
Aufträge
Auftrag 0
- Game überlegen, mit LP besprechen und …
- … absegnen lassen
Die Kriterien an das Game sind:
- Spiel in Konsole.
- Ihr dürft ein bereits bekanntes Spiel implementieren. Ihr könnt aber auch ein eigenes erfinden oder ein bestehende abändern/erweitern. (→ Kriterium: Spielidee, Originalität)
- Es ist ein neues Spiel, ihr habt diese also nicht bereits im Vorfeld programmiert.
- Gibt nach erfolgreichem Spielen einen Score zurück: absolviertes Level und Anzahl Punkte (z.B. gesammelte Punkte, Spieldauer in Sekunden, Anzahl Versuche, …)
- Es ist auch möglich (und sogar wünschenswert), verschiedene Levels zu haben. Das Ziel wäre dann, ein möglichst hohes Level mit einem möglichst guten Score zu erzielen.
- Das Game wird selbständig und komplett von euch programmiert.
- Der programmiererische Schwierigkeitsgrad eures Games entspricht in etwa euren Vorkenntnissen: Z.B. wird von den Talits mehr erwartet!
- Es gibt für alle eine mündliche Prüfung. Dort müsst ihr demonstrieren, dass ihr euer Programm komplett versteht.
Auftrag I: HangMan im Framework
Auftrag in Kürze: HangMan in Framework integrieren und in ein Single-Player-Game umwandeln.
Auftrag im Detail:
- Erstelle ein GitHub-Repo mit Namen
ConsoleGame(wähle Gitignore „Visual Studio“) und klone es auf Computer. Alle erstellen ihr eigenes Repo. Für das eigentliche Game-Project wird dann ein neues Repo erzeugt.
- Lade das Framework herunter und entzippe es. Füge den Inhalt dem Repo zu. Add, commit, push. Verschaffe dir nun einen groben Überblick über das Framework:
- Programm ausführen und ausprobieren, spielen
- Welche Files, Klassen, Methoden usw. gibt es?
- Insbesondere Code von Spiel
GuessNumberstudieren.
- Integriere nun dein HangMan-Spiel in das Framework:
- Erstelle eine neue Klasse (neues File) mit Namen „HangMan“, in welche der Code des Spiels kommt:
Projektmappe / rechte Maustaste auf Ordner „Games“ / Hinzufügen / neue Klasse - Grundsätzlich kommt der Inhalt der Main-Methode von der alten Version in die Play-Methode
- Die zusätzlich benötigten Funktionen von Modell und View werden parallel zur Play-Methode eingefügt. Diese müssen mit dem Zugangmodifizierer
publicoderprivateversehen werden. Überlege dir, welcher für welche Funktion passend ist.- Public methods: Framework kann diese von aussen aufrufen, z.B. von
Program.csaus. - Private methods: Können nur von innerhalb der Klasse aufgerufen werden, z.B. in der Play-Methode der gleichen Klasse.
- Die Play-Methode muss ein Score-Objekt zurückgeben. Für den Moment kannst du einfach ein leeres zurückgeben:
return new Score(); - Nun solltest du dein HangMan-Spiel innerhalb des Frameworks spielen können.
- HangMan v2.0: Das Problem ist noch, dass das HangMan in der jetzigen Fassung ein 2-Player Game ist. Wandle es nun in ein Singleplayer-Game um und gebe einen sinnvollen Score zurück:
- Das gesuchte Wort soll aus einem Array von vorgegebenen Wörtern per Zufall ausgewählt werden. Man kann die vorgegebenen Arrays unten verwenden oder eigene erstellen.
- Das Spiel soll mind. 3 Levels haben. Mit jedem höheren Level kommen schwierigere Wörter vor. Erzeuge ein passendes Score-Objekt und gib dieses am Ende der Play-Methode zurück. Tipp: Schaue in „GuessNumber“ nach, wie das gemacht wird.
- Optional: Speichere die Wörterlisten in einem File (z.B. CSV oder JSON) und lese dieses ein.
Q: Was ist der Unterschied von Funktion und Methode? A: Eine Methode ist eine Funktion, die zu einer Klasse gehört.
Auftrag II: Eigenes Game programmieren
Vorgehen
- Sicherstellen, dass Projekt von Lehrpersonen abgesegnet wurde
- Repo den Lehrpersonen freigeben.
- Beginnen mit Arbeiten.
- Tipp: Zuerst Planen, Modellieren & Skizzieren, erst dann Programmieren!
- Regelmässige und unaufgeforderte Commits & Pushes, ca. 2x pro Woche
- Pünktliche Abgabe: Sende Game-Klasse(n) (NICHT das gesamte VS Projekt) und/oder GitHub-Repo per Teams-Chat an sca (freigeben für anschae)
- Verspätete Abgabe: 0.25 Note pro angebrochene 24h Verspätung
Bewertung
Das Game wird mit einer Note bewertet.
| Kriterium | Punkte |
|---|---|
| Spielidee, Originalität, Komplexität | 10 |
| Prozess, Vorgehensweise, Selbständigkeit (1) | 10 |
| kontinuierliches Arbeiten und Fortschritt | |
| regelmässige Commits (und Pushes) auf GitHub | |
| mehrheitlich selbständig gearbeitet | |
| Arbeiten mit Framework | 10 |
| Plug n' Play (einfaches Einbinden in Framework) | |
| Gesamter Code in einem File | |
| private vs. public | |
| Model vs. View | 10 |
| Modellierung (Abstrahierung) | |
| Aufteilung in Methoden & Klassen (letztere optional) | |
| Strikte Trennung von Model- und View-Methoden/Klassen | |
| GUI / Darstellung | 10 |
| anspruchsvolles GUI, Anwendung der Console-Befehle | |
| Programmieren | 15 |
| Benennung von Variablen, Methoden usw. | |
| sauber und effizient programmiert | |
| Logik | |
| Stabilität, Umgang mit falschen Eingaben | |
| Gamespezifischer Teil | 15 |
| unterschiedlicher Fokus je nach Game | |
| Mündliche Prüfung (2) | 20 |
| Total | 100 |
Aus den Punkten wird die Note linear berechnet (95% der Punkte: 6er, 0 Punkte: 1er).
- (1) Für allgemeine Fragen zu C#, dem Framework und OOP stehen die Lehrpersonen euch gerne zur Verfügung. Die konkrete Umsetzung des Games sollt ihr aber möglichst ohne Hilfe hinkriegen.
- (2) Disclaimer: In der Prüfung müsst ihr uns überzeugen, dass ihr euer Game komplett selbständig programmiert habt. Zweifeln wir daran, führt dies zu zusätzlichem (massivem) Abzug. „ChatGPT hat mir das gesagt.“ ist keine Erklärung!
Theorie
Kommentare zur Dokumentation
Dokumentiere die wichtigen Methoden, Felder und Eigenschaften professionel: Siehe offiziellen Guidelines für "Documentation Comments"
Console Befehle
// Clear console Console.Clear(); // Hide cursor Console.CursorVisible = false; // Write line Console.WriteLine(); // Write at specific position Console.SetCursorPosition(20,10); Console.Write(); // Read current cursor position (int left, int top) = Console.GetCursorPosition(); // Read input Console.ReadLine(); Console.ReadKey(); // Using color Console.BackgroundColor = ConsoleColor.Yellow; Console.ForegroundColor = ConsoleColor.Red; // font color // Get terminal windows width and height Console.WindowWidth; Console.WindowHeight;
Delays & Sleep
Für mehr Infos, siehe Slides zu ConsoleArt
using System.Threading; // for sleep using System.Diagnostics; // for stopwatch // Let program sleep Thread.Sleep(500); // Stopwatch: Measures time since program start Stopwatch stopwatch = Stopwatch.StartNew(); long time = stopwatch.ElapsedMilliseconds;
Key event listener
Auf User-Input warten, z.B. für Game-Steuerung:
while (true) { if (Console.KeyAvailable) { ConsoleKeyInfo key = Console.ReadKey(); Console.WriteLine("key pressed: " + key.Key); } else { Console.WriteLine("no key pressed"); } Thread.Sleep(200); // sleep for 200ms, requires using System.Threading; }
Mehrdimensionale Arrays
// declare 2d-array and set array element values: int[,] arr = { { 1, 4, 2 }, { 3, 6, 8 } }; // declare 2d-array without setting element values (int array -> default elements are 0): int[,] arr2 = new int[3, 5]; // looks like this: // | column 1 | column 2 | column 3 | // row 1 | 1 | 4 | 2 | // row 2 | 3 | 6 | 8 | // Access element: Console.WriteLine(arr[1, 2]); // Outputs 8 // Change element: arr[0, 0] = 5; // Value 1 -> 5 // Get total number of elements in array Console.WriteLine(arr.Length); // Get dimension of array (nr columns and rows) Console.WriteLine(arr.GetLength(0)); // -> 2 (y-direction) Console.WriteLine(arr.GetLength(1)); // -> 3 (x-direction) // IMPORTANT: order is different than in math: first y, then x // Iterate over elements Console.WriteLine(); for (int y = 0; y < arr.GetLength(0); y++) { for (int x = 0; x < arr.GetLength(1); x++) { Console.WriteLine(arr[y,x]); } }
OOP
private class Point { // Field public int x; public int y; public string color; // Constructor public Point(int _x, int _y, string _color) { x = _x; y = _y; color = _color; } // Methode public void SetToStart() { x = 0; y = 0; } } private class PointWithProperty { // Field private int _x; private int _y; private string _color; // Property public int x { get { return _x; } set { if (value > 0) { _x = value; } else { _x = 0; } } } // Constructor public PointWithProperty(int _xx, int _yy, string _col) { _x = _xx; _y = _yy; _color = _col; } // Methode public void SetToStart() { _x = 0; _y = 0; } } public override Score Play(int level) { Console.CursorVisible = false; Point p = new Point(10, 7, "red"); // create new point object Console.SetCursorPosition(p.x, p.y); Console.Write(p.color); Console.ReadKey(); p.SetToStart(); // call method Console.SetCursorPosition(p.x, p.y); Console.Write(p.color); Console.ReadKey(); // Point is new data type, can thus create point array Point[] points = new Point[] { new Point(1, 1, "black"), new Point(7, 5, "yellow"), new Point(2, 12, "green") }; return new Score(); }
Kriterien
- Model View, Modellierung
- Documentation Comments
- Grafik
- Plug n Play
- Kann (fast) jederzeit aus Game ausbrechen, ohne Programm schliessen zu müssen (z.B. 'q' drücken)