Das Kartenspiel Mau-Mau

1. Aufgabe

Wir betrachten in dieser Aufgabe den bekannten Kartenspiel-Klassiker Mau-Mau. Für das Spiel sind eine Reihe von C#-Klassen zu entwickeln, die wir in den ersten Abschnitten zunächst unabhängig voneinander betrachten. Erst am Schluss der Aufgabe fügen wir diese Klassen zu einem Ganzen zusammen. Die Grundregeln des Spiels sind folgende:

Spielvorbereitung::

  • An einem Kartentisch sitzen mehrere Kartenspieler zusammen. Auf dem Tisch liegt ein Stapel mit verdeckten Spielkarten.

  • Jeder Spieler erhält vor Spielbeginn fünf Karten. Dann wird eine Karte vom Stapel genommen und aufgedeckt. Während des Spiels gibt es also zwei Kartenstapel: Einen Stapel zum Ziehen von (verdeckten) Karten (Ziehstapel), einen zweiten Stapel zum Ablegen von (aufgedeckten) Karten (Ablagestapel).

Spielverlauf:

  • Derjenige Spieler, der an der Reihe ist, legt eine seiner Karten offen auf den Ablagestapel. Die Karte, die der Spieler ablegen möchte, muss entweder die gleiche Farbe (Karo, Herz, Pik, Kreuz) oder das gleiche Bild (Sieben, Acht, Neun, Zehn, Dame, König, Ass) wie die zuletzt aufgedeckte Karte haben. Auf die Pik-10 darf also entweder eine andere Pik-Karte oder eine andere 10 gelegt werden. Kann ein Spieler keine Karte ablegen, muss er eine Karte vom Ziehstapel ziehen und warten, bis er erneut an der Reihe ist.

  • Ist der Stapel mit den verdeckten Karten irgendwann aufgebraucht, so werden die abgelegten Karten, außer der obersten, gemischt und als neuer Stapel ausgelegt.

  • Gewonnen hat, wer zuerst alle seine Karten abgelegt hat. Das Spiel wird mit den übrigen Spielern solange fortgesetzt, bis nur noch ein Spieler übrig bleibt.

Karten mit besonderer Bedeutung:

  • Karte mit Bild Acht:

    Legt ein Spieler eine Acht auf die aufgedeckte Karte, dann muss der nächste Spieler einmal aussetzen. Bei zwei Spielern ist dann derjenige, der die Acht ausgelegt hat, erneut an der Reihe.

  • Karte mit Bild Bube:

    Ein Bube kann grundsätzlich auf alle Karten gelegt werden. Legt ein Spieler einen Buben, darf er sich eine Farbe wünschen. Die nächste Karte, die auf den Buben gelegt wird, muss dann diese Farbe haben. Besitzt der nächste Spieler diese Farbe nicht, so muss er – wie gehabt – eine Karte ziehen.

  • Karte mit Bild Sieben:

    Legt ein Spieler eine Sieben auf die aufgedeckte Karte, dann muss der nächste Spieler zwei Karten ziehen. Sollte er jedoch ebenfalls eine Sieben haben, dann kann er sie auf die bereits abgelegte Sieben legen und braucht keine Karten zu ziehen. Der nächste Spieler muss dann aber vier Karten ziehen, der übernächste 6 usw.

Mau-Mau kennt neben dem oben beschriebenen Standardregelwerk zahlreiche weitere Varianten, sie spielen für diese Aufgabe keine Rolle! Wir beschreiben nun im Folgenden eine mögliche Strukturierung der Aufgabenstellung an Hand des geschickten Entwurfs einiger zentraler Klassen detaillierter.

1.1. Klasse Card

Wir gehen als Erstes auf die Klasse Card ein. Jede Karte des Kartenspiels wird durch ein Card-Objekt repräsentiert. Ein Card-Objekt wird durch die Kartenfarbe und das Kartenbild eindeutig beschrieben. Zu diesem Zweck definieren wir zwei Aufzählungstypen CardColor und CardPicture:

enum CardColor { Empty, Karo, Herz, Pik, Kreuz }

und

enum CardPicture { Empty, Sieben, Acht, Neun, Zehn, Bube, Dame, König, Ass }

Mit ihrer Hilfe können Sie nun die Klasse Karte realisieren, entnehmen Sie weitere Hilfestellungen dazu Tabelle 1:

Element

Schnittstelle und Beschreibung

Konstruktor

public Card (CardColor color, CardPicture picture);

Der Konstruktor dient zum Erzeugen eines Kartenobjekts. Die beiden Parameter color und picture legen die Details der Karte fest.

Eigenschaft CardColor

public CardColor Color { get; }

Liefert die Farbe einer Spielkarte zurück.

Eigenschaft CardPicture

public CardPicture Picture { get; }

Liefert das Bild einer Spielkarte zurück.

Tabelle 1. Zentrale Elemente der Klasse Card.


Mit welcher Methode lassen sich – konform zum .NET-Objektmodell – zwei Spielkarten geeignet auf Gleichheit vergleichen? Überschreiben Sie ferner die ToString-Methode geeignet, um ein Card-Objekt auf der Konsole ausgeben zu können.

Bemerkung: In der Realisierung der Klasse Card bietet es sich an, das .NET-Sprachmittel struct anzuwenden. Da beim Spielen viele Card-Objekte vorhanden sind und diese im Wesentlichen nur aus den zwei Werten für Kartenbild und -farbe bestehen, wären leichtgewichtige Objekte zu bevorzugen. Die Arbeit des Garbage Collectors kann auf diese Weise sinnvoll reduziert werden.

Testrahmen für Klasse Card:

// test frame for Card objects
Card card1 = new Card(CardColor.Kreuz, CardPicture.Neun);
Card card2 = new Card(CardColor.Pik, CardPicture.König);
Card card3 = new Card(CardColor.Kreuz, CardPicture.Neun);

Console.WriteLine(card1);
Console.WriteLine(card2);

Console.WriteLine("Farbe: {0}", card1.Color);
Console.WriteLine("Bild:  {0}", card2.Picture);

if (card1.Equals(card2))
    Console.WriteLine("Die Karten sind gleich");
else
    Console.WriteLine("Die Karten sind verschieden");

Console.WriteLine(card1.Equals (card3));

Ausgabe:

Kreuz Neun
Pik König
Farbe: Kreuz
Bild:  König
Die Karten sind verschieden
True

1.2. Klasse CardDeck

Auf dem Spieltisch liegen während eines Mau-Mau-Spiels zwei Kartenstapel: Einer zum Ziehen von Karten und ein zweiter zum Ablegen. Die Verwaltung eines solchen Kartenstapels obliegt der Klasse CardDeck. Implementieren Sie – auf möglichst einfache Weise – die Klasse CardDeck mit den in Tabelle 2 beschriebenen Methoden.

Neben den üblichen Methoden Push, Pop und IsEmpty gibt es auch die Methode TopOfStack. Sie ist vor allem für den Stapel mit den abgelegten Karten relevant, da die Spieler stets sehen müssen, welche Karte als letztes abgelegt wurde und folglich als oberste Karte aufliegt. Für den Stapel zum Ziehen von Karten wäre ein Aufruf der TopOfStack-Methode natürlich tabu.

Element

Schnittstelle und Beschreibung

Eigenschaft Size

public int Size { get; }

Liefert die Anzahl der Karten des Stapels zurück.

Methode Push

public void Push(Card card);

Dient zum Ablegen einer Karte card auf dem Kartenstapel.

Methode Pop

public Card Pop();

Dient zum Abheben einer Karte vom Kartenstapel.

Methode Fill

public void Fill();

Dient zum Vorbelegen des Stapels mit allen verfügbaren Karten.

Methode Shuffle

public void Shuffle();

Mit Shuffle lassen sich die Karten des Stapels mischen.

Eigenschaft TopOfStack

public Card TopOfDeck { get; }

Dient zum Betrachten der obersten Karte des Kartenstapels. Die Karte wird nicht vom Stapel entfernt!

Eigenschaft IsEmpty

public bool IsEmpty { get; }

Mit IsEmpty lässt sich feststellen, ob der Kartenstapel noch Karten enthält oder leer ist.

Tabelle 2. Zentrale Methoden und Eigenschaften der Klasse CardDeck.


Testrahmen für Klasse CardDeck:

// test frame for CardDeck object
Card card1 = new Card(CardColor.Kreuz, CardPicture.Neun);
Card card2 = new Card(CardColor.Pik, CardPicture.König);
Card card3 = new Card(CardColor.Herz, CardPicture.Sieben);

CardDeck deck = new CardDeck();
deck.Push(card1);
deck.Push(card2);
deck.Push(card3);

Console.WriteLine(deck);

Ausgabe:

 1: Kreuz Neun
 2: Pik König
 3: Herz Sieben

1.3. Klasse CardSet

Beim Spielen von Mau-Mau hält jeder Spieler eine bestimmte Menge von Spielkarten in der Hand. Die Klasse CardDeck ist dazu nicht geeignet. Möchte man beispielsweise eine Karte ablegen, kann man von einem Stapel nur die oberste Karte entfernen. Eine beliebige Karte innerhalb des Stapels kann nicht gezogen werden. Wir benötigen deshalb eine zweite einfache Hilfsklasse CardSet.

Eine Beschreibung der wichtigsten Methoden und Eigenschaften der Klasse CardSet finden Sie in Tabelle 3 vor:

Element

Schnittstelle und Beschreibung

Eigenschaft Size

public int Size { get; }

Ermittelt die Anzahl der Karten in der Kartenmenge.

Methode Add

public void Add(Card card);

Fügt eine Karte card zur Kartenmenge hinzu.

Methode Remove

public void Remove(int index);

Entfernt die Karte mit dem Index index aus der Kartenmenge.

Indexer

public Card this [int index] { get; }

Liefert die Karte mit dem Index index aus der Kartenmenge zurück. Die Karte wird dabei aus der Menge nicht entfernt.

Tabelle 3. Zentrale Methoden und Eigenschaften der Klasse CardSet.


Testrahmen für Klasse CardSet:

// test frame for a single CardSet object
Card card1 = new Card(CardColor.Kreuz, CardPicture.Neun);
Card card2 = new Card(CardColor.Pik, CardPicture.König);
Card card3 = new Card(CardColor.Herz, CardPicture.Sieben);

CardSet set = new CardSet();
set.Add(card1);
set.Add(card2);
set.Add(card3);

for (int i = 0; i < set.Size; i++)
{
    Console.WriteLine("Karte {0}: {1}", i, set[i]);
}

Console.WriteLine("Karten auf der Hand: {0}", set);
set.Remove(1);
Console.WriteLine("Karten auf der Hand: {0}", set);

Ausgabe:

Karte 0: Kreuz Neun
Karte 1: Pik König
Karte 2: Herz Sieben
Karten auf der Hand: Kreuz Neun, Pik König, Herz Sieben
Karten auf der Hand: Kreuz Neun, Herz Sieben

1.4. Klasse Player

Jeder Spieler von Mau-Mau hat einen Namen und kennt zwei Kartenstapel: Einen Stapel zum Ablegen der Karten und einen zweiten Stapel zum Ziehen von Karten – also zwei CardDeck-Objekte. Ein Spieler hält eine bestimmte Menge von Karten in der Hand, er hat also ein CardSet-Objekt. Die Methoden des Spielers, die in Tabelle 4 spezifiziert sind, sind auf die Logik des Mau-Mau-Spiels abgestimmt. Mit der Methode ChooseAColor wird beispielsweise ein bestimmter Spieler gefragt, welche Farbe als nächstes für die abzulegenden Karten zu Grunde zu legen ist (wenn zuvor ein Bube abgelegt wurde).

Element

Schnittstelle und Beschreibung

Konstruktor

public Player(String name);

Der Konstruktor dient zum Erzeugen eines Player-Objekts. Die Parameter name legt den Namen des Spielers fest.

Eigenschaft PlayingDeck

public CardDeck PlayingDeck { set; }

Dient zum Setzen des Kartenstapels zum Ablegen.

Eigenschaft DrawingDeck

public CardDeck DrawingDeck { set; }

Dient zum Setzen des Kartenstapels zum Ziehen.

Eigenschaft Name

public String Name { get; set; }

Dient zum Lesen und Schreiben des Spielernamens.

Eigenschaft NumberCards

public int NumberCards { get; }

Liefert die Anzahl der Karten zurück, die ein Spieler in der Hand hält.

Eigenschaft IsPlaying

public bool IsPlaying { get; }

Zeigt an, ob der Spieler noch „im Spiel“ ist (true) oder bereits all seine Karten ablegen konnte (false).

Methode ChooseAColor

public CardColor ChooseAColor();

Wird ein Bube abgelegt, darf sich der aktuelle Spieler eine Farbe wünschen, die für den nächsten Spieler gilt. Es empfiehlt sich, eine Farbe zu wählen, von der der aktuelle Spieler Karten besitzt.

Methode DrawCards

public void DrawCards(int number);

Kann ein Spieler keine Karte ablegen, muss er eine Karte ziehen – im Falle einer zuvor abgelegten Sieben sind es sogar mehrere. Der Parameter number gibt an, wie viele Karten der Spieler ziehen muss.

Methode PlayCard

public bool PlayCard (CardColor requestedColor, CardPicture requestedPicture);

Mit PlayCard wird ein Spieler aufgefordert, eine Karte abzulegen. Die beiden Parameter requestedColor und requestedPicture spezifizieren die oberste Karte des Kartenstapels zum Ablegen. Die abzulegende Karte muss also entweder diese Farbe oder dieses Bild haben. Kann ein Spieler keine Karte ablegen, verlässt er die Methode PlayCard mit dem Rückgabewert false, andernfalls mit true.

Methode PlayCard

public bool PlayCard (CardColor requestedColor);

Ist im Prinzip wie die zuvor beschriebene Überladung von PlayCard zu implementieren, nur: Liegt auf dem Kartenstapel zum Ablegen der Karten ein Bube, ist von den nachfolgenden Spielern eine Karte an Hand der Kartenfarbe abzulegen. Das Kartenbild kann also ignoriert werden, die Methode enthält nur einen einzigen Parameter requestedColor für die Kartenfarbe.

Methode PlayArbitraryCard

public void PlayArbitraryCard();

Nach dem Aufnehmen von einer oder mehreren Karten auf Grund einer zuvor gespielten Sieben kann der aktuelle Spieler mit dem Ablegen einer beliebigen Karte fortfahren. Zu diesem Zweck gibt es die PlayArbitraryCard-Methode.

Methode CounterSeven

public bool CounterSeven(int numCardsToDraw);

Wurde eine Sieben abgelegt, ist es für den nächsten Spieler von Vorteil, ebenfalls eine Sieben abzulegen. Zu diesem Zweck gibt es die Methode CounterSeven mit einem int-Parameter numCardsToDraw. Besitzt der aktuelle Spieler eine Sieben, legt er diese ab und verlässt die Methode mit Rückgabe von true (der Parameter numCardsToDraw wird ignoriert). Im anderen Fall muss der Spieler die Anzahl von numCardsToDraw Spielkarten auf dem Kartenstapel zum Ablegen ablegen. Die Methode liefert in diesem Fall true zurück.

Tabelle 4. Zentrale Methoden und Eigenschaften der Klasse Player.

1.5. Klasse MauMaster

Ein MauMaster-Objekt besitzt zwei Kartenstapel zum Ablegen und Ziehen und verwaltet mehrere Spieler. Das Kernstück der Klasse MauMaster ist die Methode Play (Tabelle 5). Sie simuliert den kompletten Ablauf eines Mau-Mau-Spiels. Im einfachsten Fall wird die jeweils aufliegende Karte betrachtet und ihre Information an den aktuellen Spieler mit PlayCard weitergereicht. Kann ein Spieler keine Karte ablegen, wird er mit DrawCards zum Ziehen einer entsprechenden Anzahl von Karten aufgefordert. Die Spezialkarten Sieben, Acht und Bube sind von der Play-Methode ebenfalls zu behandeln.

Methode

Schnittstelle und Beschreibung

Konstruktor

public MauMaster(String[] names);

Im Konstruktor werden zuerst zwei CardDeck-Objekte und mehrere Player-Objekte erzeugt. Die Namen und Anzahl der Player-Objekte wird durch den Parameter names bestimmt. Jeder der Spieler nimmt fünf Karten in seine Hand auf.

Methode Play

public void Play ();

Führt den kompletten Ablauf eines Mau-Mau-Spiels durch.

Tipp: Implementieren Sie die Methode Play zunächst ohne Betrachtung der Sonderregeln für die drei Karten Sieben, Acht und Bube. Ergänzen Sie dann eine Sonderregel nach der anderen.

Tabelle 5. Zentrale Methoden der Klasse MauMaster.

1.6. Ein Beispiel

Das folgende Beispiel demonstriert, wie der Ablauf Ihres Programms aussehen könnte. Es sind für alle zentralen Aktionen wie Karte ziehen oder ablegen entsprechende Ausgaben zu machen. An Hand der Ausgaben muss die Einhaltung der Spielregeln von Mau-Mau nachvollziehbar sein:

------------------------------------------------------------------
    Simple Mau-Mau Cards Game (Version 1.00)
------------------------------------------------------------------
>   Hans draws Karo König from drawing deck!
>   Hans draws Karo Zehn from drawing deck!
>   Hans draws Kreuz Ass from drawing deck!
>   Sepp draws Herz Ass from drawing deck!
>   Sepp draws Kreuz Zehn from drawing deck!
>   Sepp draws Kreuz Dame from drawing deck!
>   Ulli draws Karo Ass from drawing deck!
>   Ulli draws Karo Neun from drawing deck!
>   Ulli draws Kreuz Sieben from drawing deck!
------------------------------------------------------------------
Topmost card: Kreuz Acht
------------------------------------------------------------------
--> Hans [X]: Karo König, Karo Zehn, Kreuz Ass
    Sepp [X]: Herz Ass, Kreuz Zehn, Kreuz Dame
    Ulli [X]: Karo Ass, Karo Neun, Kreuz Sieben
------------------------------------------------------------------
>   '8' is on top of deck - skip next player
------------------------------------------------------------------
Topmost card: Kreuz Acht
------------------------------------------------------------------
    Hans [X]: Karo König, Karo Zehn, Kreuz Ass
--> Sepp [X]: Herz Ass, Kreuz Zehn, Kreuz Dame
    Ulli [X]: Karo Ass, Karo Neun, Kreuz Sieben
------------------------------------------------------------------
>   Sepp plays Kreuz Zehn
------------------------------------------------------------------
Topmost card: Kreuz Zehn
------------------------------------------------------------------
    Hans [X]: Karo König, Karo Zehn, Kreuz Ass
    Sepp [X]: Herz Ass, Kreuz Dame
--> Ulli [X]: Karo Ass, Karo Neun, Kreuz Sieben
------------------------------------------------------------------
>   Ulli plays Kreuz Sieben
------------------------------------------------------------------
Topmost card: Kreuz Sieben
------------------------------------------------------------------
--> Hans [X]: Karo König, Karo Zehn, Kreuz Ass
    Sepp [X]: Herz Ass, Kreuz Dame
    Ulli [X]: Karo Ass, Karo Neun
------------------------------------------------------------------
>   '7' is on top of deck
>   Hans cannot respond to '7', draws 2 card(s)!
>   Hans draws Herz Zehn from drawing deck!
>   Hans draws Pik Bube from drawing deck!
>   Hans plays Pik Bube
>   Hans has choosen color Karo
------------------------------------------------------------------
Topmost card: Pik Bube
------------------------------------------------------------------
    Hans [X]: Karo König, Karo Zehn, Kreuz Ass, Herz Zehn
--> Sepp [X]: Herz Ass, Kreuz Dame
    Ulli [X]: Karo Ass, Karo Neun
------------------------------------------------------------------
>   Sepp cannot serve, draws 1 card(s)
>   Sepp draws Pik Zehn from drawing deck!
------------------------------------------------------------------
Topmost card: Pik Bube
------------------------------------------------------------------
    Hans [X]: Karo König, Karo Zehn, Kreuz Ass, Herz Zehn
    Sepp [X]: Herz Ass, Kreuz Dame, Pik Zehn
--> Ulli [X]: Karo Ass, Karo Neun
------------------------------------------------------------------
>   Ulli plays Karo Ass
==> Ulli says 'Mau'
------------------------------------------------------------------
Topmost card: Karo Ass
------------------------------------------------------------------
--> Hans [X]: Karo König, Karo Zehn, Kreuz Ass, Herz Zehn
    Sepp [X]: Herz Ass, Kreuz Dame, Pik Zehn
    Ulli [X]: Karo Neun
------------------------------------------------------------------
>   Hans plays Karo König
------------------------------------------------------------------
Topmost card: Karo König
------------------------------------------------------------------
    Hans [X]: Karo Zehn, Kreuz Ass, Herz Zehn
--> Sepp [X]: Herz Ass, Kreuz Dame, Pik Zehn
    Ulli [X]: Karo Neun
------------------------------------------------------------------
>   Sepp cannot serve, draws 1 card(s)
>   Sepp draws Pik Acht from drawing deck!
------------------------------------------------------------------
Topmost card: Karo König
------------------------------------------------------------------
    Hans [X]: Karo Zehn, Kreuz Ass, Herz Zehn
    Sepp [X]: Herz Ass, Kreuz Dame, Pik Zehn, Pik Acht
--> Ulli [X]: Karo Neun
------------------------------------------------------------------
>   Ulli plays Karo Neun
##> Ulli says 'MAU MAU !!!'
>   Ulli quits game !
------------------------------------------------------------------
Topmost card: Karo Neun
------------------------------------------------------------------
--> Hans [X]: Karo Zehn, Kreuz Ass, Herz Zehn
    Sepp [X]: Herz Ass, Kreuz Dame, Pik Zehn, Pik Acht
    Ulli [-]
------------------------------------------------------------------
>   Hans plays Karo Zehn
------------------------------------------------------------------
Topmost card: Karo Zehn
------------------------------------------------------------------
    Hans [X]: Kreuz Ass, Herz Zehn
--> Sepp [X]: Herz Ass, Kreuz Dame, Pik Zehn, Pik Acht
    Ulli [-]
------------------------------------------------------------------
>   Sepp plays Pik Zehn
------------------------------------------------------------------
Topmost card: Pik Zehn
------------------------------------------------------------------
--> Hans [X]: Kreuz Ass, Herz Zehn
    Sepp [X]: Herz Ass, Kreuz Dame, Pik Acht
    Ulli [-]
------------------------------------------------------------------
>   Hans plays Herz Zehn
==> Hans says 'Mau'
------------------------------------------------------------------
Topmost card: Herz Zehn
------------------------------------------------------------------
    Hans [X]: Kreuz Ass
--> Sepp [X]: Herz Ass, Kreuz Dame, Pik Acht
    Ulli [-]
------------------------------------------------------------------
>   Sepp plays Herz Ass
------------------------------------------------------------------
Topmost card: Herz Ass
------------------------------------------------------------------
--> Hans [X]: Kreuz Ass
    Sepp [X]: Kreuz Dame, Pik Acht
    Ulli [-]
------------------------------------------------------------------
>   Hans plays Kreuz Ass
##> Hans says 'MAU MAU !!!'
>   Hans quits game !
Sepp has lost --- Game over [14]

2. Lösung

Quellcode: Siehe auch github.com/peterloos/CSharp_MauMau.git.

Die Hilfestellungen im Aufgabenteil waren sehr umfangreich gestaltet – wir können uns daher im Lösungsteil direkt der Realisierung der einzelnen Klassen Card, CardDeck, CardSet, Player, MauMaster und Program zuwenden (Listing 1, Listing 2, Listing 3, Listing 4, Listing 5 und Listing 6):

01: using System;
02: 
03: struct Card
04: {
05:     private CardColor color;
06:     private CardPicture picture;
07: 
08:     // c'tor
09:     public Card(CardColor color, CardPicture picture)
10:     {
11:         this.color = color;
12:         this.picture = picture;
13:     }
14: 
15:     // properties
16:     public CardColor Color
17:     {
18:         get
19:         {
20:             return this.color;
21:         }
22:     }
23: 
24:     public CardPicture Picture
25:     {
26:         get
27:         {
28:             return this.picture;
29:         }
30:     }
31: 
32:     // overrides
33:     public override bool Equals(Object obj)
34:     {
35:         if (obj == null || !(obj is Card))
36:             return false;
37: 
38:         Card tmp = (Card) obj;
39:         return (this.color == tmp.color && this.picture == tmp.picture);
40:     }
41: 
42:     public override String ToString()
43:     {
44:         return String.Format("{0} {1}", this.color, this.picture);
45:     }
46: 
47:     public override int GetHashCode()
48:     {
49:         return base.GetHashCode();
50:     }
51: }

Beispiel 1. Klasse Card


001: using System;
002: using System.Collections.Generic;
003: 
004: class CardDeck
005: {
006:     private List<Card> deck;
007:     private Random rand;
008: 
009:     // c'tor(s)
010:     public CardDeck()
011:     {
012:         this.deck = new List<Card>();
013:     }
014: 
015:     // properties
016:     public Random Rand
017:     {
018:         set
019:         {
020:             this.rand = value;
021:         }
022:     }
023: 
024:     public int Size
025:     {
026:         get
027:         {
028:             return this.deck.Count;
029:         }
030:     }
031: 
032:     public bool IsEmpty
033:     {
034:         get
035:         {
036:             return this.deck.Count == 0;
037:         }
038:     }
039: 
040:     public Card TopOfDeck
041:     {
042:         get
043:         {
044:             if (this.IsEmpty)
045:             {
046:                 throw new IndexOutOfRangeException("TopOfDeck::CardDeck is emtpy !");
047:             }
048: 
049:             Card card = this.deck[this.deck.Count - 1];
050:             return card;
051:         }
052:     }
053: 
054:     // public interface
055:     public void Push(Card card)
056:     {
057:         this.deck.Add(card);
058:     }
059: 
060:     public Card Pop()
061:     {
062:         if (this.IsEmpty)
063:         {
064:             throw new IndexOutOfRangeException("Pop::CardDeck is emtpy !");
065:         }
066: 
067:         Card card = this.deck[this.deck.Count - 1];
068:         this.deck.RemoveAt(this.deck.Count - 1);
069:         return card;
070:     }
071: 
072:     public void Fill()
073:     {
074:         // fill deck with all available cards
075:         for (int i = 1; i <= 4; i++)
076:         {
077:             for (int j = 1; j <= 8; j++)
078:             {
079:                 Card card = new Card((CardColor) i, (CardPicture) j);
080:                 this.deck.Add(card);
081:             }
082:         }
083:     }
084: 
085:     public void Clear()
086:     {
087:         this.deck.Clear();
088:     }
089: 
090:     public void Shuffle()
091:     {
092:         // mix deck by random
093:         const int ShuffleCount = 30;
094: 
095:         for (int i = 0; i < ShuffleCount; i++)
096:         {
097:             int index1 = this.rand.Next(this.deck.Count);
098:             int index2 = this.rand.Next(this.deck.Count);
099: 
100:             if (index1 != index2)
101:             {
102:                 Card temp = this.deck[index1];
103:                 this.deck[index1] = this.deck[index2];
104:                 this.deck[index2] = temp;
105:             }
106:         }
107:     }
108: 
109:     // overrides
110:     public override String ToString()
111:     {
112:         String s = String.Empty;
113:         for (int i = 0; i < this.deck.Count; i++)
114:         {
115:             s += String.Format("{0,2}: {1}", (i + 1), this.deck[i]);
116:             s += Environment.NewLine;
117:         }
118: 
119:         return s;
120:     }
121: }

Beispiel 2. Klasse CardDeck


01: using System;
02: using System.Collections.Generic;
03: 
04: class CardSet
05: {
06:     private List<Card> set;
07: 
08:     // c'tor(s)
09:     public CardSet ()
10:     {
11:         this.set = new List<Card>();
12:     }
13: 
14:     // properties
15:     public int Size
16:     {
17:         get
18:         {
19:             return this.set.Count;
20:         }
21:     }
22: 
23:     // indexer
24:     public Card this [int index]
25:     {
26:         get
27:         {
28:             return this.set[index];
29:         }
30:     }
31: 
32:     // public interface
33:     public void Add(Card card)
34:     {
35:         this.set.Add(card);
36:     }
37: 
38:     public void Remove(int index)
39:     {
40:         if (index < 0 || index >= this.set.Count)
41:         {
42:             String msg = String.Format("Wrong Index {0} !", index);
43:             throw new IndexOutOfRangeException(msg);
44:         }
45: 
46:         this.set.RemoveAt(index);
47:     }
48: 
49:     // overrides
50:     public override String ToString()
51:     {
52:         String s = "";
53:         for (int i = 0; i < this.set.Count; i++)
54:         {
55:             s += this.set[i];
56:             if (i < this.set.Count - 1)
57:                 s += ", ";
58:         }
59:         return s;
60:     }
61: }

Beispiel 3. Klasse CardSet


001: using System;
002: 
003: class Player
004: {
005:     private CardSet  hand;       // player's hand of cards (usually 5)
006:     private CardDeck playing;    // deck to play (Kartenstapel zum Ablegen)
007:     private CardDeck drawing;    // deck to draw (Kartenstapel zum Ziehen)
008:     private String   name;       // players name
009:     private bool     isPlaying;  // false, after getting rid of all cards
010: 
011:     // c'tors
012:     public Player(String name)
013:     {
014:         this.hand = new CardSet();
015:         this.name = name;
016:         this.isPlaying = true;
017:         this.playing = null;   // yet to be provided - see property 'PlayingDeck'
018:         this.drawing = null;   // yet to be provided - see property 'DrawingDeck'
019:     }
020: 
021:     public Player(String name, CardDeck playing, CardDeck drawing) : this(name)
022:     {
023:         this.playing = playing;
024:         this.drawing = drawing;
025:     }
026: 
027:     // properties
028:     public int NumberCards
029:     {
030:         get
031:         {
032:             return this.hand.Size;
033:         }
034:     }
035: 
036:     public String Name
037:     {
038:         get
039:         {
040:             return this.name;
041:         }
042: 
043:         set
044:         {
045:             this.name = value;
046:         }
047:     }
048: 
049:     public CardDeck PlayingDeck
050:     {
051:         set
052:         {
053:             this.playing = value;
054:         }
055:     }
056: 
057:     public CardDeck DrawingDeck
058:     {
059:         set
060:         {
061:             this.drawing = value;
062:         }
063:     }
064: 
065:     public bool IsPlaying
066:     {
067:         get
068:         {
069:             return this.isPlaying;
070:         }
071: 
072:         set
073:         {
074:             this.isPlaying = value;
075:         }
076:     }
077: 
078:     // public interface
079:     public CardColor ChooseAColor()
080:     {
081:         if (this.hand.Size > 0)
082:         {
083:             // players has (still) some cards in his hand
084:             return this.hand[0].Color;
085:         }
086:         else
087:         {
088:             // players has no more cards, chooses arbitrary card color
089:             return CardColor.Herz;
090:         }
091:     }
092: 
093:     public void DrawCards(int number)
094:     {
095:         for (int i = 0; i < number; i++)
096:         {
097:             Card card = this.DrawCard();
098:             this.hand.Add(card);
099: 
100:             String msg = String.Format(">   {0} draws {1} from drawing deck!", this.name, card);
101:             MauMaster.Log(msg);
102:         }
103:     }
104: 
105:     public bool CounterSeven(int numCardsToDraw)
106:     {
107:         if (this.HasSeven())
108:         {
109:             // players holds '7' in his hand
110:             String msg = String.Format(">   {0} counters '7' with another '7' !", this.name);
111:             MauMaster.Log(msg);
112: 
113:             this.PlaySeven();
114:             return true;
115:         }
116:         else
117:         {
118:             // players must draw cards
119:             String msg = String.Format(">   {0} cannot respond to '7', draws {1} card(s)!",
120:                 this.name, numCardsToDraw);
121:             MauMaster.Log(msg);
122: 
123:             this.DrawCards(numCardsToDraw);
124:             return false;
125:         }
126:     }
127: 
128:     public bool PlayCard(CardColor requestedColor, CardPicture requestedPicture)
129:     {
130:         for (int i = 0; i < this.hand.Size; i++)
131:         {
132:             Card card = this.hand[i];
133:             if (card.Color == requestedColor || card.Picture == requestedPicture)
134:             {
135:                 this.hand.Remove(i);
136:                 this.playing.Push(card);
137:                 String s = String.Format(">   {0} plays {1}", this.name, card);
138:                 MauMaster.Log(s);
139:                 this.PrintMauMauIf();
140:                 return true;
141:             }
142:         }
143: 
144:         // 'Bube' maybe played upon every card!
145:         for (int i = 0; i < this.hand.Size; i++)
146:         {
147:             Card card = this.hand[i];
148:             if (card.Picture == CardPicture.Bube)
149:             {
150:                 this.hand.Remove(i);
151:                 this.playing.Push(card);
152:                 String s = String.Format(">   {0} plays {1}", this.name, card);
153:                 MauMaster.Log(s);
154:                 this.PrintMauMauIf();
155:                 return true;
156:             }
157:         }
158: 
159:         return false;
160:     }
161: 
162:     public bool PlayCard(CardColor requestedColor)
163:     {
164:         for (int i = 0; i < this.hand.Size; i++)
165:         {
166:             Card card = this.hand[i];
167: 
168:             // 'Bube' upon 'Bube' not allowed ("Bube auf Bube" stinkt)
169:             if (card.Picture == CardPicture.Bube)
170:                 continue;
171: 
172:             if (card.Color == requestedColor)
173:             {
174:                 this.hand.Remove(i);
175:                 this.playing.Push(card);
176:                 String s = String.Format(">   {0} plays {1}", this.name, card);
177:                 MauMaster.Log(s);
178:                 this.PrintMauMauIf();
179:                 return true;
180:             }
181:         }
182: 
183:         return false;
184:     }
185: 
186:     public void PlayArbitraryCard()
187:     {
188:         int lastIndex = this.hand.Size - 1;
189:         Card card = this.hand[lastIndex];
190:         this.hand.Remove(lastIndex);
191:         this.playing.Push(card);
192:         String s = String.Format(">   {0} plays {1}", this.name, card);
193:         MauMaster.Log(s);
194:         this.PrintMauMauIf();
195:     }
196: 
197:     // private helper methods
198:     private Card DrawCard()
199:     {
200:         // turn over playing deck to serve as new drawing deck
201:         if (this.drawing.Size == 0)
202:         {
203:             MauMaster.Log(">   turn over playing deck to serve as new drawing deck");
204: 
205:             // save topmost card of playing stack
206:             Card topmostPlayingCard = this.playing.Pop();
207: 
208:             // copy rest of playing deck to drawing deck
209:             while (!this.playing.IsEmpty)
210:             {
211:                 Card tmp = this.playing.Pop();
212:                 this.drawing.Push(tmp);
213:             }
214: 
215:             // shuffle drawing stack
216:             this.drawing.Shuffle();
217: 
218:             // restore topmost card of playing stack
219:             this.playing.Push(topmostPlayingCard);
220:         }
221: 
222:         return this.drawing.Pop();
223:     }
224: 
225:     private bool HasSeven()
226:     {
227:         for (int i = 0; i < this.hand.Size; i++)
228:         {
229:             Card c = this.hand[i];
230:             if (c.Picture == CardPicture.Sieben)
231:                 return true;
232:         }
233: 
234:         return false;
235:     }
236: 
237:     private void PlaySeven()
238:     {
239:         for (int i = 0; i < this.hand.Size; i++)
240:         {
241:             Card card = this.hand[i];
242:             if (card.Picture == CardPicture.Sieben)
243:             {
244:                 this.hand.Remove(i);
245:                 this.playing.Push(card);
246:                 String s = String.Format(">   {0} drops {1} onto deck!", this.name, card);
247:                 MauMaster.Log(s);
248:                 this.PrintMauMauIf();
249:                 return;
250:             }
251:         }
252: 
253:         throw new InvalidOperationException("ERROR (PlaySeven): Should never be reached");
254:     }
255: 
256:     private void PrintMauMauIf()
257:     {
258:         if (this.hand.Size == 1)
259:         {
260:             String s = String.Format("==> {0} says 'Mau'", this.name);
261:             MauMaster.Log(s);
262:         }
263:         else if (this.hand.Size == 0)
264:         {
265:             String s = String.Format("##> {0} says 'MAU MAU !!!'", this.name);
266:             MauMaster.Log(s);
267:         }
268:     }
269: 
270:     // overrides
271:     public override String ToString()
272:     {
273:         String s = String.Format("{0} [{1}]", this.name, this.isPlaying ? "X" : "-");
274:         if (this.hand.Size > 0)
275:         {
276:             s += ": ";
277:             s += this.hand.ToString();
278:         }
279:         return s;
280:     }
281: }

Beispiel 4. Klasse Player


001: #define VERBOSE
002: #define SINGLE_STEP
003: 
004: using System;
005: 
006: class MauMaster
007: {
008:     private const String Version = "    Simple Mau-Mau Cards Game (Version 1.00)";
009:     private const int MaxCardsAtBegin = 5;  // used for testing - should be 5 regularly
010: 
011:     private CardDeck playing;  // deck to play (Kartenstapel zum Ablegen - offen)
012:     private CardDeck drawing;  // deck to draw (Kartenstapel zum Ziehen - verdeckt)
013:     private Player[] players;  // array of players
014:     private int rounds;        // counting rounds of a game
015: 
016:     // c'tor(s)
017:     public MauMaster(String[] names)
018:     {
019:         // create two card decks
020:         this.playing = new CardDeck();  // deck to play (Kartenstapel zum Ablegen)
021:         this.drawing = new CardDeck();  // deck to draw (Kartenstapel zum Ziehen)
022: 
023:         // create array of players
024:         this.players = new Player[names.Length];
025:         for (int i = 0; i < this.players.Length; i++)
026:         {
027:             this.players[i] = new Player(names[i]) { PlayingDeck = playing, DrawingDeck = drawing };
028:         }
029:     }
030: 
031:     // properties
032:     public int Rounds
033:     {
034:         get
035:         {
036:             return this.rounds;
037:         }
038:     }
039: 
040:     // public interface
041:     public void Init(int randomSeed)
042:     {
043:         // create new random generator (prefer unique results to make testing more easier)
044:         Random rand = new Random(randomSeed);
045:         this.playing.Rand = rand;
046:         this.drawing.Rand = rand;
047: 
048:         // intialize card decks
049:         this.playing.Clear();
050:         this.drawing.Fill();       // fill deck with all available cards ...
051:         this.drawing.Shuffle();    // ... and mix them ...
052: 
053:         for (int i = 0; i < this.players.Length; i++)
054:         {
055:             this.players[i].IsPlaying = true;
056:             this.players[i].DrawCards(MaxCardsAtBegin);  // draw initial amount of cards
057:         }
058: 
059:         this.rounds = 0;
060:     }
061: 
062:     public void Play()
063:     {
064:         // controlling game variables
065:         int numberOfCardsToDraw = 2;
066:         int activePlayers = this.players.Length;
067:         int currentPlayer = 0;
068:         CardColor requestedCardColor = CardColor.Empty;
069: 
070:         // controlling special games state 'Bube'
071:         bool bubeIsActive = false;
072: 
073:         // controlling special games states '8'
074:         bool eightIsActive = false;
075:         bool skipNextPlayer = false;
076: 
077:         // uncover first card
078:         Card firstCard = this.drawing.Pop();
079:         this.playing.Push(firstCard);
080: 
081:         // and now lets play an aweful game
082:         while (activePlayers > 1)
083:         {
084:             Card topMostCard = this.playing.TopOfDeck;
085:             this.LogGameStatusDebug(topMostCard, currentPlayer);   // debug/verbose output            
086: 
087:             this.rounds++;  // count rounds of this game
088: 
089:             // handle special cards
090:             if (topMostCard.Picture == CardPicture.Sieben)
091:             {
092:                 // '7' is on top of card deck
093:                 Log(">   '7' is on top of deck");
094:                 if (this.players[currentPlayer].CounterSeven(numberOfCardsToDraw))
095:                 {
096:                     numberOfCardsToDraw = this.IncrementNumberOfCardsToDraw(numberOfCardsToDraw);
097:                 }
098:                 else
099:                 {
100:                     numberOfCardsToDraw = 2;  // no more '7' on top of card deck
101: 
102:                     // player may now draw a card, if he can
103:                     this.players[currentPlayer].PlayArbitraryCard();
104: 
105:                     Card peek = this.playing.TopOfDeck;
106: 
107:                     if (peek.Picture == CardPicture.Bube)
108:                     {
109:                         requestedCardColor = this.players[currentPlayer].ChooseAColor();
110: 
111:                         bubeIsActive = true;
112: 
113:                         String msg = String.Format(">   {0} has choosen color {1}",
114:                             this.players[currentPlayer].Name, requestedCardColor);
115:                         Log(msg);
116:                     }
117:                     else if (peek.Picture == CardPicture.Acht)
118:                     {
119:                         Log(">   '8' is on top of deck - skip next player");
120:                         eightIsActive = true;
121:                         skipNextPlayer = true;
122:                     }
123:                 }
124:             }
125:             else if (topMostCard.Picture == CardPicture.Acht && !eightIsActive)
126:             {
127:                 Log(">   '8' is on top of deck - skip next player");
128:                 eightIsActive = true;
129:                 skipNextPlayer = false;
130:             }
131:             else if (topMostCard.Picture == CardPicture.Bube && !bubeIsActive)
132:             {
133:                 requestedCardColor = this.players[currentPlayer].ChooseAColor();
134: 
135:                 bubeIsActive = true;
136: 
137:                 String msg = String.Format(">   {0} has choosen color {1}",
138:                     this.players[currentPlayer].Name, requestedCardColor);
139:                 Log(msg);
140:             }
141:             else
142:             {
143:                 // regular mode -- no special cards --
144:                 // current player plays according to "standard" rules
145:                 bool success;
146:                 if (! bubeIsActive)
147:                 {
148:                     // picture or color can be played
149:                     success = 
150:                         this.players[currentPlayer].PlayCard(topMostCard.Color, topMostCard.Picture);
151:                 }
152:                 else
153:                 {
154:                     // a color has been choosen right before, only color must match
155:                     success = 
156:                         this.players[currentPlayer].PlayCard(requestedCardColor);
157:                 }
158: 
159:                 if (success)
160:                 {
161:                     // reset special state(s), if any 
162:                     eightIsActive = false;
163:                     bubeIsActive = false;
164: 
165:                     Card peek = this.playing.TopOfDeck;
166:                     if (peek.Picture == CardPicture.Bube)
167:                     {
168:                         requestedCardColor = this.players[currentPlayer].ChooseAColor();
169: 
170:                         bubeIsActive = true;
171: 
172:                         String msg = String.Format(">   {0} has choosen color {1}",
173:                             this.players[currentPlayer].Name, requestedCardColor);
174:                         Log(msg);
175:                     }
176:                     else if (peek.Picture == CardPicture.Acht)
177:                     {
178:                         Log(">   '8' is on top of deck - skip next player");
179: 
180:                         eightIsActive = true;
181:                         skipNextPlayer = true;
182:                     }
183:                 }
184:                 else
185:                 {
186:                     String msg = String.Format(">   {0} cannot serve, draws {1} card(s)",
187:                         this.players[currentPlayer].Name, 1);
188:                     Log(msg);
189: 
190:                     this.players[currentPlayer].DrawCards(1);
191:                 }
192:             }
193: 
194:             // test, if current player quits
195:             if (this.players[currentPlayer].NumberCards == 0)
196:             {
197:                 String msg = String.Format(">   {0} quits game !", this.players[currentPlayer].Name);
198:                 Log(msg);
199: 
200:                 this.players[currentPlayer].IsPlaying = false;
201:                 activePlayers--;
202:             }
203: 
204:             // switch to next player
205:             currentPlayer = this.NextPlayer(currentPlayer);
206: 
207:             // '8' has just been played, next player pauses
208:             if (skipNextPlayer == true)
209:             {
210:                 // skip next player
211:                 currentPlayer = this.NextPlayer(currentPlayer);
212: 
213:                 skipNextPlayer = false;
214:             }
215:         }
216: 
217:         // last player loses the game
218:         this.LogFinalGameStatus(this.players[currentPlayer].Name);
219:     }
220: 
221:     public static String[] ReadPlayers()
222:     {
223:         Console.Write("Number of Players: ");
224:         String s = Console.ReadLine();
225:         int n = Int32.Parse(s);
226: 
227:         String[] names = new String[n];
228:         for (int i = 0; i < n; i++)
229:         {
230:             Console.Write("{0}. Player: ", (i+1));
231:             names[i] = Console.ReadLine();
232:         }
233: 
234:         return names;
235:     }
236: 
237:     public static void PrintVersion()
238:     {
239:         Console.WriteLine("------------------------------------------------------------------");
240:         Console.WriteLine(MauMaster.Version);
241:         Console.WriteLine("------------------------------------------------------------------");
242:     }
243: 
244:     // private helper methods
245:     private int NextPlayer(int currentPlayer)
246:     {
247:         // move to next player
248:         currentPlayer++;
249:         if (currentPlayer == this.players.Length)
250:             currentPlayer = 0;
251: 
252:         // search next array slot with still active player
253:         while (!this.players[currentPlayer].IsPlaying)
254:         {
255:             currentPlayer++;
256:             if (currentPlayer == this.players.Length)
257:                 currentPlayer = 0;
258:         }
259: 
260:         return currentPlayer;
261:     }
262: 
263:     private int IncrementNumberOfCardsToDraw(int numberOfCardsToDraw)
264:     {
265:         numberOfCardsToDraw += 2;
266:         return numberOfCardsToDraw;
267:     }
268: 
269:     private void LogFinalGameStatus(String name)
270:     {
271: #if VERBOSE
272:         Console.WriteLine("{0} has lost --- Game over [{1}]", name, this.rounds);
273: #endif
274:     }
275: 
276:     private void LogGameStatusDebug(Card topMostCard, int currentPlayer)
277:     {
278: #if VERBOSE
279:         Console.WriteLine("------------------------------------------------------------------");
280:         Console.WriteLine("Topmost card: {0}", topMostCard);
281:         Console.WriteLine("------------------------------------------------------------------");
282: 
283:         for (int i = 0; i < this.players.Length; i++)
284:         {
285:             String prefix = (i == currentPlayer) ? "-->" : "   ";
286:             String s = String.Format("{0} {1}", prefix, this.players[i]);
287:             Console.WriteLine(s);
288:         }
289: 
290:         Console.WriteLine("------------------------------------------------------------------");
291: #endif
292: 
293: #if SINGLE_STEP
294:         Console.ReadKey();  // just for testing
295: #endif
296:     }
297: 
298:     public static void Log (String message)
299:     {
300: #if VERBOSE
301:         Console.WriteLine(message);
302: #endif
303:     }
304: }

Beispiel 5. Klasse MauMaster


001: using System;
002: 
003: class Program
004: {
005:     private static void TestUnit_01_Cards ()
006:     {
007:         // test frame for Card objects
008:         Card card1 = new Card(CardColor.Kreuz, CardPicture.Neun);
009:         Card card2 = new Card(CardColor.Pik, CardPicture.König);
010:         Card card3 = new Card(CardColor.Kreuz, CardPicture.Neun);
011: 
012:         Console.WriteLine(card1);
013:         Console.WriteLine(card2);
014: 
015:         Console.WriteLine("Farbe: {0}", card1.Color);
016:         Console.WriteLine("Bild:  {0}", card2.Picture);
017: 
018:         if (card1.Equals(card2))
019:             Console.WriteLine("Die Karten sind gleich");
020:         else
021:             Console.WriteLine("Die Karten sind verschieden");
022: 
023:         Console.WriteLine(card1.Equals (card3));
024:     }
025: 
026:     private static void TestUnit_02_CardDeck()
027:     {
028:         Random rand = new Random(1);
029: 
030:         // test frame for CardDeck objects
031:         Card card1 = new Card(CardColor.Kreuz, CardPicture.Neun);
032:         Card card2 = new Card(CardColor.Pik, CardPicture.König);
033:         Card card3 = new Card(CardColor.Herz, CardPicture.Sieben);
034: 
035:         CardDeck deck = new CardDeck() { Rand = rand };
036:         deck.Push(card1);
037:         deck.Push(card2);
038:         deck.Push(card3);
039: 
040:         Console.WriteLine(deck);
041:     }
042: 
043:     private static void TestUnit_03_CardDeck()
044:     {
045:         Random rand = new Random(1);
046: 
047:         // test frame for CardDeck objects
048:         CardDeck deck = new CardDeck() { Rand = rand };
049:         deck.Fill();
050:         Console.WriteLine(deck);
051:         deck.Shuffle();
052:         Console.WriteLine(deck);
053:     }
054: 
055:     private static void TestUnit_04_CardSet()
056:     {
057:         // test frame for a single CardSet object
058:         Card card1 = new Card(CardColor.Kreuz, CardPicture.Neun);
059:         Card card2 = new Card(CardColor.Pik, CardPicture.König);
060:         Card card3 = new Card(CardColor.Herz, CardPicture.Sieben);
061: 
062:         CardSet set = new CardSet();
063:         set.Add(card1);
064:         set.Add(card2);
065:         set.Add(card3);
066: 
067:         for (int i = 0; i < set.Size; i++)
068:         {
069:             Console.WriteLine("Karte {0}: {1}", i, set[i]);
070:         }
071: 
072:         Console.WriteLine("Karten auf der Hand: {0}", set);
073:         set.Remove(1);
074:         Console.WriteLine("Karten auf der Hand: {0}", set);
075:     }
076: 
077:     private static void TestUnit_09_PlayTheGame()
078:     {
079:         MauMaster.PrintVersion();
080:         String[] names = MauMaster.ReadPlayers();
081:         MauMaster mm = new MauMaster(names);
082:         mm.Init(1);
083:         mm.Play();
084:     }
085: 
086:     private static void TestUnit_10_StressTestMauMaster()
087:     {
088:         MauMaster.PrintVersion();
089:         MauMaster mm = new MauMaster(new String[] { "Hans", "Sepp", "Ulli" });
090: 
091:         int minRounds = Int32.MaxValue;
092:         int minRoundsIndex = -1;
093:         int maxRounds = -1;
094:         int maxRoundsIndex = -1;
095: 
096:         for (int i = 1; i < 1000; i++)
097:         {
098:             mm.Init(i);
099:             mm.Play();
100: 
101:             if (mm.Rounds < minRounds)
102:             {
103:                 minRounds = mm.Rounds;
104:                 minRoundsIndex = i;
105:             }
106: 
107:             if (mm.Rounds > maxRounds)
108:             {
109:                 maxRounds = mm.Rounds;
110:                 maxRoundsIndex = i;
111:             }
112: 
113:             Console.WriteLine("Game at {0,5}: {1}", i, mm.Rounds);    
114:         }
115: 
116:         Console.WriteLine("Minumum number of rounds: {0} [Index {1}]", minRounds, minRoundsIndex);
117:         Console.WriteLine("Maximum number of rounds: {0} [Index {1}]", maxRounds, maxRoundsIndex);
118:     }
119: 
120:     private static void TestUnit_11_SingleTestMauMaster()
121:     {
122:         MauMaster.PrintVersion();
123:         MauMaster mm = new MauMaster(new String[] { "Hans", "Sepp", "Ulli" });
124:         int randomSeed = 188;
125:         mm.Init(randomSeed);
126:         mm.Play();
127:     }
128: 
129:     public static void Main()
130:     {
131:         // TestUnit_01_Cards();
132:         // TestUnit_02_CardDeck();
133:         // TestUnit_03_CardDeck();
134:         // TestUnit_04_CardSet();
135:         // TestUnit_09_PlayTheGame();
136:         // TestUnit_10_StressTestMauMaster();
137:         TestUnit_11_SingleTestMauMaster();
138:     }
139: }

Beispiel 6. Klasse Program