====== 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 =====
{{ :ef_informatik:efif_console_games_uebersicht.pdf |Slides ConsoleGames 01 Übersicht}}
{{ :ef_informatik:efif_consolegames_modellieren.pdf |Slides ConsoleGames 02 Modellieren}}
{{ :ef_informatik:efif_consolegames_consoleart.pdf |Slides ConsoleGames 03 ConsoleArt}}
===== Framework =====
{{ :ef_informatik:consolegames2025v01.zip |ConsoleGames 2025 v01}}
===== 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:**
1. 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.\\ \\
1. 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:
1. Programm ausführen und ausprobieren, spielen
1. Welche Files, Klassen, Methoden usw. gibt es?
1. Insbesondere Code von Spiel `GuessNumber` studieren.\\ \\
1. **Integriere** nun dein **HangMan-Spiel** in das Framework:
1. 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
1. Grundsätzlich kommt der Inhalt der Main-Methode von der alten Version in die Play-Methode
1. Die zusätzlich benötigten Funktionen von Modell und View werden *parallel* zur Play-Methode eingefügt. Diese müssen mit dem **Zugangmodifizierer** `public` oder `private` versehen werden. Überlege dir, welcher für welche Funktion passend ist.
1. Public methods: Framework kann diese von aussen aufrufen, z.B. von `Program.cs` aus.
1. Private methods: Können nur von *innerhalb der Klasse* aufgerufen werden, z.B. in der Play-Methode der gleichen Klasse.
1. Die Play-Methode muss ein Score-Objekt zurückgeben. Für den Moment kannst du einfach ein leeres zurückgeben: `return new Score();`
1. Nun solltest du dein HangMan-Spiel innerhalb des Frameworks spielen können.\\ \\
1. **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:
1. 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.
1. 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.
1. *Optional:* Speichere die Wörterlisten in einem File (z.B. CSV oder JSON) und lese dieses ein.
++++Arrays mit Wörtern|
string[] wordsSimple = new string[] { "Hund", "Katze", "Haus", "Auto", "Apfel", "Tisch", "Stuhl", "Buch", "Fenster", "Tür", "Wasser", "Baum", "Blume", "Sonne", "Mond", "Tag", "Nacht", "Ball", "Kind", "Schule"};
string[] wordsMedium = new string[] { "Bibliothek", "Abenteuer", "Geheimnis", "Symphonie", "Expedition", "Karriere", "Toleranz", "Illusion", "Revolution", "Koordination", "Vision", "Harmonie", "Konsequenz", "Inspiration", "Kreativität", "Perspektive", "Emotion", "Rhythmus", "Universum", "Innovation", "Mysterium" };
string[] wordsAdvanced = new string[] { "Paradox", "Ambivalenz", "Konnotation", "Konstellation", "Subjektiv", "Pragmatik", "Divergenz", "Osmose", "Symbiose", "Dissonanz", "Redundanz", "Hyperbel", "Polymorph", "Metamorphose", "Obsession", "Resonanz"};
++++
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 ===
1. Sicherstellen, dass Projekt von Lehrpersonen **abgesegnet** wurde
1. Repo den Lehrpersonen **freigeben**.
1. Beginnen mit Arbeiten.
1. **Tipp:** Zuerst Planen, Modellieren & Skizzieren, erst dann Programmieren!
1. Regelmässige und unaufgeforderte **Commits & Pushes**, ca. 2x pro Woche
1. **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)
1. **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!
++++ Kommentare|
Änderungen für 2025 usw: Gute Kommentierung in Code sollten auch Punkte geben, zB 10 dafür, aber nur 10 für mündl. P oder so
++++
===== Theorie =====
==== Kommentare zur Dokumentation ====
Dokumentiere die wichtigen Methoden, Felder und Eigenschaften *professionel*: Siehe [[https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/documentation-comments|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)