home Funktionale Programmierung: Tic Tac Toe Prof. Dr. Uwe Schmidt FH Wedel

Tic Tac Toe

weiter

weiter

Aufgabe

ist eine einfaches 2-Personen Brettspiel auf einem 3x3-Brett. Bei Wikipedia gibt es mehr Information hierüber.
Ziel
dieser Aufgabe ist es, die Funktionen zu entwickeln, die für den Spielalgorithmus wesentlich sind. In dieser Aufgabe soll von der Größe des Spielfeldes abstrahiert werden, so dass man also auch ein 4x4-, 5x5- oder NxN TicTacToe spielen könnte.
2. Ziel
Dieses ist ein kleines Trainingslager für die Verarbeitung von Listen mit map, fold und verwandten Funktionen. Versuchen Sie auch, bei der Entwicklung mehrere Varianten zu konstruieren (point wise, point free, list comprehension).
Data.List
ist eine Fundgrube für Funktionen, die die Entwicklung der Algorithmen vereinfachen können. Auch im Prelude gibt es einige sehr brauchbare Funktionen. Also:
 
module TicTacToe
where
 
import Data.List
...
Brett
Folgende Datentypen seien vorgegeben:
 
type Board = [Row]
type Row   = [Field]
 
data Field = B | X | O
             deriving (Eq, Show)
Erzeugen
von leeren Spielfeldern:
?
newBoard3       :: Board
newBoard3       = [[B,B,B],[B,B,B],[B,B,B]]
 
newBoard        :: Int -> Board
newBoard n      = ???
Spuren
Entwickeln Sie eine Funktion zur Berechnung aller Vektoren aus den Zeilen, Spalten und Diagonalen.
Die Reihenfolge der Vektoren ist nicht wesentlich
?
tracks          :: Board -> [Row]
tracks b        = ???
 
 
b1              = [ [X,B,B]                  -- ein Brettzustand
                  , [X,O,B]
                  , [B,O,B]
                  ]
tracks b1       = [ [X,O,B]                   -- Diagonale
                  , [B,O,B]                   -- Nebendiagonale
                  , [X,B,B], [X,O,B], [B,O,B] -- Zeilen
                  , [X,X,B], [B,O,O], [B,B,B] -- Spalten
                  ]
Züge
Aus einem Brettzustand sind für einen Spieler, O oder X, eine Liste von Folgenzuständen möglich.
Entwickeln Sie hierfür eine Funktion moves:
?
moves           :: Field -> Board -> [Board]
moves x b       = ???
Gewonnen
Entwickeln Sie eine Testfunktion, ob eine Spieler, O oder X, gewonnen hat.
?
won             :: Field -> Board -> Bool
won x           = ???
Beendet
Entwickeln Sie eine Testfunktion, für die Überprüfung, ob das Spiel zu Ende ist.
?
finished        :: Board -> Bool
finished b      = ???
Gewinnchance
Entwickeln Sie eine Testfunktion, die überprüft, ob mit dem nächsten Zug ein Spieler, O oder X, gewinnen kann.
?
winMoves        :: Field -> Board -> [Board]
winMoves x      = ???
Alle Spiele
Entwickeln Sie eine Funktion, die aus einer Folge von Steinen, üblicherweise abwechselnd Xe und Os, alle Spielzustände generiert.
?
play            :: [Field] -> Board -> [Board]
play xs b       = ???
Ausgabe
Zur einfachen Ausgabe der Brettzustände dienen die folgenden Funktionen:
 
toc B   = ' '
toc X   = 'X'
toc O   = 'O'
 
showRow         :: Row -> String
showRow         = intercalate "|" . map ((:[]) . toc)
 
showBoard       :: Board -> String
showBoard b     = ("\n" ++) . intercalate ln  . map (++ "\n") $ rs
                  where
                  rs = map showRow b
                  ln = replicate (length (head rs)) '-' ++ "\n"
 
printBoard      = putStrLn . showBoard
printBoards     = mapM_ printBoard
Tests
Ein paar (zu) wenige Tests
 
t0 = printBoards $                                    play [X]         $ newBoard3
t1 = printBoards $                                    play [X,O]       $ newBoard3
t2 = printBoards $ filter (not . null . winMoves X) . play [X,O]       $ newBoard3
t3 = printBoards $ filter (not . null . winMoves O) . play [X,O,X]     $ newBoard3
t4 = printBoards $ filter (not . null . winMoves X) . play [X,O,X,O]   $ newBoard3
t5 = printBoards $ filter (not . null . winMoves O) . play [X,O,X,O,X] $ newBoard3
merke
Versuchen Sie etwas systematischere und sinvollere Test zu entwickeln.

Letzte Änderung: 27.03.2015
© Prof. Dr. Uwe Schmidt
Prof. Dr. Uwe Schmidt FH Wedel