import System import Char import List -- Datentypen -- -- Spielfeld data Board = Wall | Cell Piece (Int, Int) Board Board Board Board Board Board -- Spielfigur data Piece = Black | White | Empty deriving (Eq) -- Main -- -- Argumente lesen main :: IO () main = do args <- getArgs proof args -- Argumente vorhanden? proof :: [String] -> IO () proof [] = putStrLn ("--\nno arguments\n" ++ usage) proof args | length args < 2 = putStrLn ("--\nno board\n" ++ usage) | otherwise = putStrLn (calc (read (args !! 0) :: Int) (args !! 1)) -- Argumente logisch? calc :: Int -> String -> String calc base str | length str /= 3*base*base-3*base+1 = ("--\nbase does not fit to board\n" ++ usage) | base < 3 || base > 10 = ("--\nbase not in range (3-10)\n" ++ usage) | otherwise = draw (parse base str 1 1) -- Graph aus String erstellen parse :: Int -> String -> Int -> Int -> Board parse base str x y | index base x y < 0 = Wall | otherwise = Cell (piece str (index base x y)) (x, y) (parse base str x (y+1)) (parse base str (x+1) (y+1)) (parse base str (x+1) y ) (parse base str x (y-1)) (parse base str (x-1) (y-1)) (parse base str (x-1) y ) -- Spielfigur bestimmen piece :: String -> Int -> Piece piece str index | length str <= index = Empty | str !! index == 'w' = White | str !! index == 'b' = Black | str !! index == 'e' = Empty -- Figur in Char umwandeln pieceToChar :: Piece -> Char pieceToChar p | p == White = 'w' | p == Black = 'b' | otherwise = 'e' -- Index aus Koordinaten berechnen index :: Int -> Int -> Int -> Int index base x y | x >= y + base = -1 | y >= x + base = -1 | x >= 2*base = -1 | y >= 2*base = -1 | x < 1 || y < 1 = -1 | y <= base = (y-1)*base + sumTo (y-2) + x - 1 | y > base && y < 2*base = sumFromTo base (2*base-1) + sumFromTo (3*base - y) (2*base-2) + x - 1 - (y - base) -- Board ausgeben draw :: Board -> String draw board = drawCells (visit board) neighbours :: Board -> [Board] neighbours board = [x | x <- neighboursAll board , isNotWall x] isNotWall :: Board -> Bool isNotWall Wall = False isNotWall board = True neighboursAll :: Board -> [Board] neighboursAll (Cell p (x,y) b1 b2 b3 b4 b5 b6) = [b1, b2, b3, b4, b5, b6] drawCells :: [Board] -> String drawCells [] = "" drawCells ((Cell p (x,y) b1 b2 b3 b4 b5 b6):xs) = (intToString x) ++ ":" ++ (intToString y) ++ "=" ++ [pieceToChar p] ++ " " ++ drawCells xs visit :: Board -> [Board] visit board = visitInternal [board] [] visitInternal :: [Board] -> [Board] -> [Board] visitInternal [] visited = visited visitInternal (x:xs) visited = visitInternal (toVisit (neighbours x) (x:visited) xs) (x:visited) toVisit :: [Board] -> [Board] -> [Board] -> [Board] toVisit [] visited to = to toVisit (x:xs) visited to | (boardNotElem x visited) && (boardNotElem x to) = toVisit xs visited (x:to) | otherwise = toVisit xs visited to boardNotElem :: Board -> [Board] -> Bool boardNotElem board [] = True boardNotElem (Cell p' (x',y') b1' b2' b3' b4' b5' b6') ((Cell p (x,y) b1 b2 b3 b4 b5 b6):xs) | x' == x && y' == y = False | otherwise = boardNotElem (Cell p' (x',y') b1' b2' b3' b4' b5' b6') xs -- Hilfsfunktionen -- -- Summe von 1 bis i sumTo :: Int -> Int sumTo i | i <= 0 = 0 | otherwise = i + sumTo (i-1) -- Summe von x bis y sumFromTo :: Int -> Int -> Int sumFromTo x y | x > y = 0 | x == y = y | x < y = x + sumFromTo (x+1) y -- Int in Char konvertieren intToChar :: Int -> Char intToChar x = chr (ord '0' + x) -- Int in String konvertieren intToString :: Int -> String intToString 0 = "" intToString number = (intToChar (mod number 10)):(intToString (quot number 10)) -- Fehlerausgabe usage :: String usage = "usage: \n"