Projekt: ConsoleGames

DEADLINE: 05.01.2024, @23.59

Ziele:

  • Zusammen eine Sammlung von Singleplayer-Konsolengames erstellen.
  • Alle steuern (alleine oder in 2er-Gruppen) 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.

Das Ziel ist, in der Klasse eine Konsolen-Game-Sammlung zu erstellen, wobei ihr alle entweder alleine oder in Zweiergruppen (Kriterien unten) 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.

  • Gruppen bilden, Kriterien:
    • Grundsätzlich wird das Projekt alleine absolviert.
    • Ausnahmsweise können Zweiergruppen genehmigt werden, aber nur falls (a) beide Personen genügend waren bei der letzten Prüfung und (b) beide Personen auf einem ähnlichen Programmierstand (vergleichbare Note) sind.
  • 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 für sämtliche Gruppenmitglieder 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!
  • Die Erwartungen an Zweiergruppen sind höher als an EinzelkämpferInnen.
  • Gegen Ende des Semesters gibt es für alle Gruppen eine mündliche Prüfung. Dort müsst ihr demonstrieren, dass ihr euer Programm komplett versteht.

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.

  2. 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
    2. Welche Files, Klassen, Methoden usw. gibt es?
    3. Insbesondere Code von Spiel GuessNumber studieren.

  3. 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
    2. Grundsätzlich kommt der Inhalt der Main-Methode von der alten Version in die Play-Methode
    3. 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.
      2. Private methods: Können nur von innerhalb der Klasse aufgerufen werden, z.B. in der Play-Methode der gleichen Klasse.
    4. Die Play-Methode muss ein Score-Objekt zurückgeben. Für den Moment kannst du einfach ein leeres zurückgeben: return new Score();
    5. Nun solltest du dein HangMan-Spiel innerhalb des Frameworks spielen können.

  4. 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.
    2. 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.
    3. Optional: Speichere die Wörterlisten in einem File (z.B. CSV oder JSON) und lese dieses ein.

Arrays mit Wörtern

Q: Was ist der Unterschied von Funktion und Methode? A: Eine Methode ist eine Funktion, die zu einer Klasse gehört.

Vorgehen

  1. Sicherstellen, dass Projekt von Lehrpersonen abgesegnet wurde
  2. Neues Repo erstellen mit passendem Namen.
  3. Repo den Lehrpersonen freigeben.
  4. Aktuelle Version von Framework herunterladen, entpacken und in Repo kopieren.
  5. Beginnen mit Arbeiten.
  6. Tipp: Zuerst Planen, Modellieren & Skizzieren, erst dann Programmieren!
  7. Regelmässige und unaufgeforderte Commits & Pushes von allen Gruppenmitgliedern, ca. 2x pro Woche
  8. Pünktliche Abgabe: Sende Game-Klasse(n) (NICHT das gesamte VS Projekt) per Teams-Chat an sca.
  9. Verspätete Abgabe: 1 Note pro angebrochene 24h Verspätung

Bewertung

Das Game einer Gruppe (1-2 Leute) wird mit einer Note bewertet. Alle Personen in der Gruppe erhalten im Normalfall die gleiche Note. Ausnahme: es ist klar ersichtlich, dass eine Person deutlich mehr beigetragen hat als die andere.

Gibt es Probleme in der Gruppe, meldet dies rechtzeitig, damit wir eine Lösung finden können.

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!

Dokumentiere die wichtigen Methoden, Felder und Eigenschaften professionel: Siehe offiziellen Guidelines für "Documentation Comments"

// Clear console
Console.Clear();
 
// Hide cursor
Console.CursorVisible = false;
 
// Write line
Console.WriteLine();
 
// Write at specific position
Console.SetCursorPosition(20,10);
Console.Write();
 
// 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;

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;

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;
}
// 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]);
    }
 
}
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();
}
  • 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)
  • ef_informatik/projekt_consolegames.1702378461.txt.gz
  • Zuletzt geändert: 2023-12-12 10:54
  • von sca