C# :: Aufgabe #217 :: Lösung #2

4 Lösungen Lösungen öffentlich
#217

Programmierung von MasterMind

Anfänger - C# von hollst - 02.07.2018 um 10:54 Uhr
MasterMind ist ein deduktives Spiel, das insbesondere Anfang der 70er Jahre sehr beliebt war.
Ziel des Spiels ist es, einen Geheimcode zu entschlüsseln.

In der klassischen Variante ordnet ein Spieler, genannt "codemaker", eine Sequenz von vier Symbolen
geheim an. Praktisch geschieht dies mittels unterschiedlich oder teilweise bzw. gänzlich
gleich gefärbter Pins oder Murmeln in einer Reihe, wobei maximal sechs Farben zur Verfügung stehen.

Ein zweiter Spieler, genannt "codebreaker", versucht durch Testmuster, gleichfalls bestehend aus vier gereihten
Symbolen (Pins/Murmeln), den Code zu erraten. Hätte der codebreaker 6 * 6 * 6 * 6 = 1.296 Versuche zur Verfügung,
wäre dies kein Problem, allerdings wird die Anzahl der Tests als Spielregel auf zwölf (manchmal weniger) begrenzt.

Als Responds auf ein Testmuster muss der codemaker zwei Informationen geben:

1.) Wieviele Symbole im Testmuster stehen an exakt der gleicher Stelle wie im Geheimmuster (im Falle vier, wäre das
Spiel für den codebreaker gewonnen) und
2.) wieviele Symbole (Pin-/Murmelfarben) sind sowohl im Geheim- als auch im Testmuster
vorhanden, allerdings nicht in übereinstimmender Position in der Reihe.

Die Programmieraufgabe bestehe nun darin, MasterMind interaktiv am PC zu simulieren, wobei der Computer als
codemaker fungiert, der zunächst per Zufallsgenerator das Geheimmuster erzeugt. Anschließend sind sukzessive
maximal zwölf Testmuster vom codebreaker (User) einzugeben und vom codemaker jeweils die zwei Fagen zu beantworten.


Anmerkung: MasterMind wurde auch von Mathematikern unter die Lupe genommen und bereits Mitte/Ende der 70er Jahre konnte
bewiesen werden, dass man es mit maximal fünf Testmustern lösen kann, sehr erstaunlich, oder? Daraufhin wurde
SuperMasterMind vorgeschlagen. Unterschied: Reihen mit fünf Symbolen und acht unterschiedlichen Pin-/Murmelfarben.

Wer MasterMind lediglich als schöne Spielerei ansieht, überlege bitte folgendes: Seit 1971 (release)
wurden bisher pro Jahr im Durchschnitt eine Million Spiele weltweit verkauft. Wärest Du der Erfinder und bekämest
als Lizenzgeber pro Exemplar 10 Cent, Du hättest finanziell ausgesorgt.
#2
vote_ok
von hollst (13980 Punkte) - 16.07.2018 um 11:49 Uhr
Quellcode ausblenden C#-Code
using System;
using static System.Console;
using System.Collections.Generic;
using System.Text;

namespace aufgabe_217_mastermind
{
    class Program
    {
        static void Main()
        {
            Random rand = new Random();
            bool bo_break = false;
            while (!bo_break)
            {
                Clear(); // = Console.Clear();
                int[] code = new int[] { rand.Next(6), rand.Next(6), rand.Next(6), rand.Next(6) };                
                int[] move = new int[4];
                Class_Mastermind cm = new Class_Mastermind(code);
                //Write(cm.getsecret());
                bool bo_game_runs = true;
                int counter = 0, max_counter = 10;
                bool bo_end1 = false;
                bool bo_end2 = false;
                while (bo_game_runs)
                {                    
                    bool bo_input_okay = false;
                    while (!bo_input_okay)
                    {
                        bo_input_okay = true;
                        Write($"give me your move (e.g. 0124 or 11 (is interpreted as 0011) or 0 (= 0000)): ");
                        int input;
                        bo_input_okay = int.TryParse(ReadLine(), out input);

                        for (var i = 0; i < move.Length; i++)
                        {
                            move[move.Length - 1 - i] = input % 10;
                            input /= 10;
                            if (move[i] > 5)
                                bo_input_okay = false;
                        }
                    }
                    counter++;
                    Clear();

                    bo_end1 = !cm.play(move);
                    bo_end2 = counter < max_counter;

                    bo_game_runs = bo_end1 && bo_end2;
                    Write(cm.movelist(bo_with_secret: false));
                }

                string info = "you have lost";
                if(!bo_end1)
                    info = "you have won";

                WriteLine($"game over: {info}{Environment.NewLine}code was {cm.getsecret()}");
                WriteLine("new game? (n = EXIT)");

                ConsoleKeyInfo ki = ReadKey(false);
                bo_break = ki.Key == ConsoleKey.N;
            }
        }
    }

    public class Class_Mastermind
    {
        int array_length;
        int[] secret;

        List<int[]> moves = new List<int[]>();

        public Class_Mastermind(int[] code)
        {
            this.array_length = code.Length;
            this.secret = new int[code.Length];
            code.CopyTo(this.secret, 0);
        }

        public bool play(int[] move)
        {
            bool bo_result = true;
            int[] temp = new int[array_length + 2];            
            for (var i = 0; i < move.Length; i++)
            {
                if (move[i] != secret[i])
                    bo_result = false;                
                temp[i + 1] = move[i];
            }
            int[] temp1 = number_of_black_and_white(secret, move);
            temp[0] = temp1[0];
            temp[temp.Length - 1] = temp1[1];
            moves.Add(temp);
            return bo_result; //true: game over
        }

        public string movelist(bool bo_with_secret = false)
        {
            StringBuilder sb = new StringBuilder();
            string sadd = string.Empty;
            for (var i = 0; i < moves.Count; i++)
            {
                if (bo_with_secret)
                    sadd = getsecret();
                sb.Append(sadd + $"{moves[i][0], 2} :");
                for (var j = 1; j < moves[i].Length - 1; j++)
                    sb.Append($"{moves[i][j], 2}");
                sb.AppendLine($" :{moves[i][moves[i].Length - 1], 2}");               
            }
            return sb.ToString();
        }

        public string getsecret()
        {
            StringBuilder sb = new StringBuilder("    ");
            for (var j = 0; j < secret.Length; j++)
                sb.Append($"{secret[j],2}");
            sb.AppendLine();
            return sb.ToString();
        }

        int[] number_of_black_and_white(int[] n, int[] ns) //according to DONALD E. KNUTH; n = code; ns = pattern
        {
            int[] result_ncode = new int[n.Length + 2];//total_number_of_hits
            int[] result_ntest = new int[ns.Length + 2];//total_number_of_misses
            int counter_black = 0;
            for (var i = 0; i < ns.Length; i++)
            {
                if (ns[i] == n[i])
                    counter_black++;

                result_ncode[ns[i]]++;
                result_ntest[n[i]]++;
            }

            int[] result = new int[2];
            for (var i = 0; i < this.array_length + 2; i++)
                result[0] += Math.Min(result_ncode[i], result_ntest[i]);
            result[1] = result[0] - counter_black;
            result[0] = counter_black;
            return result;
        }
    }
}

Kommentare:

Für diese Lösung gibt es noch keinen Kommentar

Bitte melden Sie sich an um eine Kommentar zu schreiben.
Kommentar schreiben