| 
       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.
         |