rendered paste bodyimport 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: <base(3-10)> <board>\n"