> ## Documentation Index
> Fetch the complete documentation index at: https://homelab.amylify.de/llms.txt
> Use this file to discover all available pages before exploring further.

# 4.2.8 Beispielprojekte

> Vier kleine C#-Konsolenprogramme zum Nachbauen: Begrüßung, Temperaturumrechner, Zahlenraten und To-do-Liste.

Programmieren lernt man durch Machen. Jedes Projekt ist ein eigenes Konsolenprogramm und übt andere Bausteine. Lege jeweils ein neues Projekt an und ersetze den Inhalt von `Program.cs`:

```powershell theme={"dark"}
dotnet new console -n MeinProjekt
cd MeinProjekt
dotnet run
```

| Projekt | Schwierigkeit | Geübt werden |
| :- | :- | :- |
| Begrüßung | Einfach | Ein- und Ausgabe, Variablen, Strings |
| Temperaturumrechner | Einfach | `switch`, `TryParse`, Methoden |
| Zahlenraten | Mittel | Schleifen, `Random`, Bedingungen |
| To-do-Liste | Anspruchsvoll | `List`, Menü, Dateien |

> [!TIP]
>
> Tippe den Code zuerst selbst ab, statt ihn zu kopieren. Danach änderst du etwas daran und schaust, was passiert. So lernst du am meisten.

***

## 1. Begrüßung

Das EVA-Prinzip in seiner einfachsten Form: Namen einlesen, Text verarbeiten, ausgeben.

```csharp Program.cs theme={"dark"}
Console.Write("Wie heißt du? ");
string? name = Console.ReadLine();

if (string.IsNullOrWhiteSpace(name))
{
    name = "Unbekannter";
}

Console.WriteLine($"Hallo {name.Trim()}! Dein Name hat {name.Trim().Length} Buchstaben.");
Console.WriteLine($"In Großbuchstaben: {name.Trim().ToUpper()}");
```

> [accordion] Erweiterungen zum Ausprobieren
>
> * Zusätzlich das Alter abfragen und das Geburtsjahr berechnen.
> * Je nach Tageszeit "Guten Morgen" oder "Guten Abend" ausgeben. Die Uhrzeit liefert `DateTime.Now.Hour`.
> * Den Namen rückwärts ausgeben.

***

## 2. Temperaturumrechner

Rechnet zwischen Celsius, Fahrenheit und Kelvin um. Die Umrechnung steckt in einer eigenen Methode.

```csharp Program.cs theme={"dark"}
Console.WriteLine("Temperaturumrechner");
Console.WriteLine("1) Celsius in Fahrenheit");
Console.WriteLine("2) Fahrenheit in Celsius");
Console.WriteLine("3) Celsius in Kelvin");
Console.Write("Auswahl: ");
string? auswahl = Console.ReadLine();

Console.Write("Temperatur: ");
if (!double.TryParse(Console.ReadLine(), out double wert))
{
    Console.WriteLine("Das war keine gültige Zahl.");
    return;
}

string ergebnis = auswahl switch
{
    "1" => $"{wert} °C = {CelsiusInFahrenheit(wert):F1} °F",
    "2" => $"{wert} °F = {FahrenheitInCelsius(wert):F1} °C",
    "3" => $"{wert} °C = {wert + 273.15:F2} K",
    _   => "Ungültige Auswahl."
};

Console.WriteLine(ergebnis);

static double CelsiusInFahrenheit(double celsius) => celsius * 9 / 5 + 32;
static double FahrenheitInCelsius(double fahrenheit) => (fahrenheit - 32) * 5 / 9;
```

> [!NOTE]
>
> Hier kommt `return;` im Hauptcode vor. In Top-Level-Programmen beendet es das Programm sofort.

> [accordion] Erweiterungen zum Ausprobieren
>
> * Eine vierte Option für Kelvin zurück in Celsius.
> * Das Programm so umbauen, dass es in einer Schleife weiterläuft, bis der Nutzer `q` eingibt.
> * Prüfen, dass Kelvin nie unter 0 liegt.

***

## 3. Zahlenraten

Der Computer denkt sich eine Zahl aus, du rätst. Nach jedem Versuch gibt es einen Hinweis.

```csharp Program.cs theme={"dark"}
Random zufall = new Random();
int gesuchteZahl = zufall.Next(1, 101);   // 1 bis 100
int versuche = 0;
bool gefunden = false;

Console.WriteLine("Ich habe mir eine Zahl zwischen 1 und 100 ausgedacht.");

while (!gefunden)
{
    Console.Write("Dein Tipp: ");

    if (!int.TryParse(Console.ReadLine(), out int tipp))
    {
        Console.WriteLine("Bitte eine ganze Zahl eingeben.");
        continue;
    }

    versuche++;

    if (tipp < gesuchteZahl)
    {
        Console.WriteLine("Zu klein.");
    }
    else if (tipp > gesuchteZahl)
    {
        Console.WriteLine("Zu groß.");
    }
    else
    {
        gefunden = true;
    }
}

Console.WriteLine($"Richtig! Du hast {versuche} Versuche gebraucht.");
```

| Baustein | Aufgabe |
| :- | :- |
| `Random.Next(1, 101)` | Zufallszahl von 1 bis **ausschließlich** 101 |
| `while (!gefunden)` | Läuft, bis die Zahl erraten ist |
| `continue` | Ungültige Eingaben zählen nicht als Versuch |

> [accordion] Erweiterungen zum Ausprobieren
>
> * Die Anzahl der Versuche auf 7 begrenzen.
> * Nach dem Spiel fragen, ob eine neue Runde gestartet werden soll.
> * Schwierigkeitsgrade mit unterschiedlichem Zahlenbereich einführen.

***

## 4. To-do-Liste

Das größte Projekt: ein Menü, eine `List<string>` und Speichern in einer Datei, damit die Aufgaben beim nächsten Start noch da sind.

```csharp Program.cs theme={"dark"}
const string DateiName = "aufgaben.txt";

List<string> aufgaben = File.Exists(DateiName)
    ? File.ReadAllLines(DateiName).ToList()
    : new List<string>();

bool laeuft = true;

while (laeuft)
{
    Console.WriteLine();
    Console.WriteLine("=== To-do-Liste ===");
    Console.WriteLine("1) Anzeigen");
    Console.WriteLine("2) Hinzufügen");
    Console.WriteLine("3) Erledigt (entfernen)");
    Console.WriteLine("4) Beenden");
    Console.Write("Auswahl: ");

    switch (Console.ReadLine())
    {
        case "1":
            ZeigeAufgaben(aufgaben);
            break;

        case "2":
            Console.Write("Neue Aufgabe: ");
            string? neu = Console.ReadLine();
            if (!string.IsNullOrWhiteSpace(neu))
            {
                aufgaben.Add(neu.Trim());
                File.WriteAllLines(DateiName, aufgaben);
            }
            break;

        case "3":
            ZeigeAufgaben(aufgaben);
            Console.Write("Nummer der erledigten Aufgabe: ");
            if (int.TryParse(Console.ReadLine(), out int nummer)
                && nummer >= 1 && nummer <= aufgaben.Count)
            {
                aufgaben.RemoveAt(nummer - 1);
                File.WriteAllLines(DateiName, aufgaben);
                Console.WriteLine("Aufgabe entfernt.");
            }
            else
            {
                Console.WriteLine("Ungültige Nummer.");
            }
            break;

        case "4":
            laeuft = false;
            break;

        default:
            Console.WriteLine("Ungültige Auswahl.");
            break;
    }
}

static void ZeigeAufgaben(List<string> liste)
{
    if (liste.Count == 0)
    {
        Console.WriteLine("Keine Aufgaben vorhanden.");
        return;
    }

    for (int i = 0; i < liste.Count; i++)
    {
        Console.WriteLine($"{i + 1}. {liste[i]}");
    }
}
```

| Konzept | Wo im Code |
| :- | :- |
| Menüschleife | `while (laeuft)` mit `switch` |
| Persistenz | `File.ReadAllLines` beim Start, `File.WriteAllLines` bei jeder Änderung |
| Eingabeprüfung | `TryParse` plus Bereichsprüfung der Nummer |
| Eigene Methode | `ZeigeAufgaben` vermeidet doppelten Code |

> [accordion] Erweiterungen zum Ausprobieren
>
> * Aufgaben als erledigt markieren, statt sie zu löschen.
> * Eine Priorität (hoch, mittel, niedrig) einführen und danach sortieren. Dafür bietet sich eine eigene Klasse oder ein `record` an.
> * Statt Textzeilen ein JSON-Format verwenden, mit `System.Text.Json`.

***

## Weitere Ideen

> [card] Passwortgenerator
>
> Zufällige Zeichen zu einem Passwort der gewünschten Länge zusammensetzen.

> [card] Würfelspiel
>
> Zwei Spieler würfeln gegeneinander, wer nach fünf Runden mehr Punkte hat, gewinnt.

> [card] Wörter zählen
>
> Eine Textdatei einlesen und mit einem `Dictionary` zählen, wie oft jedes Wort vorkommt.

> [card] Bankkonto-Simulation
>
> Eine Klasse `Konto` mit Ein- und Auszahlung und Fehlern bei zu hohen Beträgen.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.