C# :: Aufgabe #306

2 Lösungen Lösungen öffentlich

Galgenraten (hangman)

Anfänger - C# von JKooP - 18.04.2020 um 12:18 Uhr
Erstelle ein Konsolenspiel in der Form „Galgenraten“.

Spieler 1 gibt verdeckt ein zu erratenes Wort ein.
Regeln: Buchstaben a-z, keine Zahlen, ä = ae, ö = oe, ü = ue, ß = ss

Spieler 2 muss versuchen die richtigen Buchstaben zu erraten.
Dazu wird am Anfang des Spiels jeder Buchstabe des Lösungsworts als „Unterstrich“ dargestellt.
Errät Spieler 2 einen Buchstaben, wird der Unterstrich an allen Positionen an der sich der gefundene Buchstabe befindet durch den jeweiligen Buchstaben ersetzt.
Es sollen am Ende des Spiels die benötigte Zeit und die Anzahl der Versuche ausgegeben werden.
Die Anzahl der Versuche soll ähnlich wie beim Galgenraten begrenzt werden.

Varianten:
Der Spieler 2 kann auch das Lösungswort eingeben. Ist das Wort falsch, wird es als 2 Fehlversuche gewertet.
Als Hilfe könnten die bereits genutzten Buchstaben angezeigt werden.
Aus der Anzahl der benötigten Versuche und der Zeit könnten Gewinnpunkte generiert werden.

Viel Spaß

Lösungen:

vote_ok
von DavidDev024 (250 Punkte) - 18.04.2020 um 18:28 Uhr
Quellcode ausblenden C#-Code
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

namespace Galgenraten
{
    class Program
    {
        
        static void Main(string[] args)
        {
            bool revealed = false;
            int wrongGuesses = 0;
            List<char> guesses = new List<char>();
            Stopwatch timer = new Stopwatch();

            //Input of the secret Word
            Console.WriteLine("Wilkommen zum Galgenraten. Spieler 1 muss sich ein geheimes Wort ausdenken, " +
                              "\nwelches dann von Spieler 2 eraten werden muss. " +
                              "\n Drehen sie nun den Bildschirm so, dass Spieler 2 nicht die Eingabe von Spieler 1 sehen kann.");

            string secretWord = ChooseWord();
            WriteWord(secretWord, guesses, ref revealed);

            //Game Loop
            timer.Start();
            while (!revealed && wrongGuesses <= 15)
            {
                if (!Guess(secretWord, guesses) == false)
                    wrongGuesses++;

                WriteWord(secretWord, guesses, ref revealed);
            }
            timer.Stop();

            //outcome of the game
            Console.Clear();
            if (revealed)
            {
                Console.WriteLine("Geschafft!");
                Console.WriteLine("Versuche: " + guesses.Count);
                Console.WriteLine("Zeit: " + timer.Elapsed);
            }
            else
            {
                Console.WriteLine("Nicht Geschafft.");
                
                Console.WriteLine("Versuche: " + guesses.Count);
                Console.WriteLine("Minuten: " + timer.Elapsed);
            }

            Console.ReadKey();
        }

        private static string ChooseWord()
        {
            string word = "";
            do
            {
                Console.Write("Spieler 1, geben Sie ihr Wort ein (a-z, keine Zahlen): ");
                word = Console.ReadLine();
            } while (word.All(char.IsDigit));
 
            return word.ToLower().Replace("ä", "ae").Replace("ö", "oe").Replace("ü", "ue").Replace("ß", "ss");
        }

        private static bool Guess(string secretWord, List<char> guesses)
        {
            Console.SetCursorPosition(0, 3);
            Console.Write("Spieler 2, rate einen Buchstaben: ");

            char guess = Console.ReadLine().ToLower().ToCharArray()[0];
            guesses.Add(guess);

            if (secretWord.Contains(guess))
            {
                return true;
            }
        
            return false;
        }

        private static void WriteWord(string secretWord, List<char> guesses, ref bool revealed)
        {
            Console.Clear();
            revealed = true;
            foreach (char c in secretWord)
            {
                if (guesses.Contains(c))//Reveale
                    Console.Write(c);
                else
                {
                    Console.Write('_');
                    revealed = false;
                }

                Console.Write(' ');
            }
        }
    }
}
vote_ok
von JKooP (18090 Punkte) - 09.08.2020 um 18:02 Uhr
NET Core 3.x

Quellcode ausblenden C#-Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using System.Text.RegularExpressions;

namespace CS_Aufgabe_306_Galgenraten
{
    enum MessageType
    {
        neutral, info, error
    }

    class Program
    {
        private const int MaxAttempts = 12;
        private const int MinWordLength = 3;

        private static int _attempt = 0;
        private static readonly Stopwatch _sw = new Stopwatch();
        private static readonly List<char> _lstLetters = new List<char>();
        private static List<char> _lstOutput;
        private static List<char> _lstInput;
        private static string _inputPlayer1;
        private static double _time;
        private static bool _showFirstLetter = false;
        private static bool _showUsedLetters = false;

        static void Main(string[] args)
        {
            // Eingaben Spieler 1 (verdeckt)
            while (true)
            {
                Console.Clear();
                Message(MessageType.neutral, "Bitte verdeckt das zu erratene Wort eingeben (nur Buchstaben): ");
                _inputPlayer1 = Console.ReadLine();

                if (CheckInput(_inputPlayer1, MinWordLength)) // nur Buchstaben zulassen
                {
                    _inputPlayer1 = Replace(_inputPlayer1); // Umlaute entfernen => Grossbuchstaben
                    Message(MessageType.neutral, $"Das zu erratene Wort ist: {_inputPlayer1} \n"); // bereinigte Ausgabe
                    Message(MessageType.neutral, "Sollen alle gewählten Buchstaben angezeigt werden (j/n)? ");
                    if (Console.ReadLine()[..1].ToUpper() == "J")
                        _showUsedLetters = true;
                    Message(MessageType.neutral, "Soll der erste Buchstabe zur Hilfe angezeigt werden (j/n)? ");
                    if (Console.ReadLine()[..1].ToUpper() == "J")
                        _showFirstLetter = true;
                    break;
                }
                else
                {
                    Message(MessageType.error, $"Das Wort muss aus mindestens {MinWordLength} Buchstaben bestehen!\nWeiter mit beliebiger Taste...");
                }
            }

            _lstInput = _inputPlayer1.ToCharArray().ToList();
            _lstOutput = new string('_', _lstInput.Count).ToCharArray().ToList();
            Console.Clear();

            if (_showFirstLetter)
                CompareLists(_lstInput[0]); // erster Buchstabe und alle Vorkommen des 1. Buchstabens werden vorbefüllt

            _sw.Start(); // Zeit läuft

            // Eingaben Spieler 2 (entweder Lösungswort oder Buchstabe)
            while (_attempt < MaxAttempts)
            {
                _attempt++;
                PrintGame();
                Console.WriteLine($"Versuch: {_attempt}/{MaxAttempts}");
                Console.Write($"Buchstabe oder Lösungswort eingeben: ");

                var inputPlayer2 = Console.ReadLine();
                if(CheckInput(inputPlayer2, 1)) // nur Buchstaben zulassen
                {
                    inputPlayer2 = Replace(inputPlayer2); // Umlaute entfernen => Grossbuchstaben
                }
                else
                {
                    Message(MessageType.error, $"Es dürfen nur Buchstaben verwendet werden!\nWeiter mit beliebiger Taste...");
                    continue;
                }

                char letter;
                if (inputPlayer2.Length != 1)
                {
                    if (_inputPlayer1 == inputPlayer2) // Wort wurde richtig geraten
                    {
                        break;
                    }
                    else
                    {
                        Message(MessageType.error, "Leider falsch! (2 Strafpunkte)\nWeiter mit beliebiger Taste...");
                        _attempt+=2;
                        continue;
                    }
                }
                else
                {
                    letter = Replace(inputPlayer2).ToCharArray()[0]; // Umlaute entfernen => Grossbuchstaben => 1. Zeichen
                }

                if (_lstLetters.Contains(letter))
                {
                    Message(MessageType.error, $"\nBuchstabe '{letter}' ist bereits gewählt worden!\nWeiter mit beliebiger Taste...");
                    continue;
                }
                else
                    _lstLetters.Add(letter);

                CompareLists(letter);

                if (!_lstOutput.Contains('_'))
                    break; // Alle Buchstaben erraten...

                _lstLetters.Sort(); // bereits gewählte Buchstaben für die Ausgabe sortieren
            }

            _sw.Stop();
            _time = _sw.Elapsed.TotalSeconds;

            PrintResult(!(_attempt > MaxAttempts));
        }

        static void CompareLists(char letter) // wenn Buchstabe in Wort vorhanden, wird Unterstrich durch Buchstabe(n) ersetzt
        {
            var k = 0;
            foreach (var l in _lstInput)
            {
                if (l == letter)
                    _lstOutput[_lstInput.IndexOf(l, k)] = l;
                k++;
            }
        }

        static void Message(MessageType t, string s = "")
        {
            switch (t)
            {
                case MessageType.neutral:
                    Console.ForegroundColor = ConsoleColor.White;
                    Console.Write(s);
                    break;
                case MessageType.error:
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine(s);
                    Console.ReadKey();
                    break;
                case MessageType.info:
                default:
                    Console.ForegroundColor = ConsoleColor.Green;
                    break;
            }
        }
        static bool CheckInput(string input, int minLength) => new Regex(@"[A-Za-zÄäÖöÜüß]{" + minLength + ",}").IsMatch(input); // nur bestimmte Zeichen zulassen

        static void PrintGame()
        {
            Console.Clear();
            if (_showUsedLetters)
            {
                Message(MessageType.info);
                Print(_lstLetters);
            }
            Message(MessageType.neutral);
            Print(_lstOutput);
        }

        static int GetPoints() => MaxAttempts / _attempt * 200 + (int)(_inputPlayer1.Length * 20 / _time) * 20; // fiktive Punkteberechnung

        static string Replace(string s) => new Dictionary<string, string> { { "ä", "ae" }, { "ö", "oe" }, { "ü", "ue" }, { "ß", "ss" } }
            .Aggregate(s, (x, y) => x.Replace(y.Key, y.Value).ToUpper()); // Umlaute entfernen

        static void Print(List<char> l) => Console.WriteLine($"\n{string.Join("", l)}\n"); // Liste für Ausgabe in String umwandeln

        static void PrintResult(bool solved)
        {
            var r = solved ? "Ja" : "Nein";
            Console.Clear();
            Console.WriteLine($"\nLösung: {_inputPlayer1}");
            Console.WriteLine($"Gelöst: {r}");
            Console.WriteLine($"Versuche: {_attempt}");
            Console.WriteLine($"Zeit: {_time:F1}s");
            Console.WriteLine($"Punkte: {(solved ? GetPoints() : 0)}");
        }
    }
}