TicTacToe
|
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 = ???
|
|
newBoard :: Int -> Board
newBoard n = replicate n . replicate n $ B
|
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]
, [X,O,B]
, [B,O,B]
]
tracks b1 = [ [X,O,B]
, [B,O,B]
, [X,B,B], [X,O,B], [B,O,B]
, [X,X,B], [B,O,O], [B,B,B]
]
|
|
tracks :: Board -> [Row]
tracks b = diag b : diag' b : rows b ++ cols b
where
rows = id
cols = transpose
diag = zipWith (flip (!!)) [0..]
diag' = diag . map reverse
|
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 = ???
|
|
moves :: Field -> Board -> [Board]
moves x [] = []
moves x (r:rs) = map (:rs) (moves' x r) ++ map (r:) (moves x rs)
moves' :: Field -> Row -> [Row]
moves' x [] = []
moves' x (B:fs) = (x:fs) : map (B:) (moves' x fs)
moves' x (y:fs) = map (y:) (moves' x fs)
|
Gewonnen |
Entwickeln Sie eine Testfunktion, ob eine Spieler, O oder X,
gewonnen hat.
|
?
|
won :: Field -> Board -> Bool
won x = ???
|
|
won :: Field -> Board -> Bool
won x = any (all (==x)) . tracks
|
Beendet |
Entwickeln Sie eine Testfunktion, für die Überprüfung,
ob das Spiel zu Ende ist.
|
?
|
finished :: Board -> Bool
finished b = ???
|
|
finished :: Board -> Bool
finished b = all (all (/= B)) b
||
won X b
||
won O 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 = ???
|
|
winMoves :: Field -> Board -> [Board]
winMoves x = filter (won x) . moves 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 = ???
|
|
play :: [Field] -> Board -> [Board]
play [] = (:[])
play (x:xs) = concat
. map (play xs)
. filter (not . finished)
. moves x
|
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
|
|
Versuchen Sie etwas systematischere und sinvollere Test zu entwickeln.
|