reversi 0.1 → 0.1.1
raw patch · 3 files changed
+106/−2 lines, 3 files
Files
- Board.hs +93/−0
- DataTypes.hs +11/−0
- reversi.cabal +2/−2
+ Board.hs view
@@ -0,0 +1,93 @@+module Board+(showBoard+,makeBoard+,move+,check+,flipChains+,hasMovesFor+,hasChain+,slice+,moves+,indexes+,value) where++import Data.Array++import DataTypes++showBoard :: Board -> IO ()+showBoard b = putStrLn $ tablerize (prettify b)+ where prettify b = foldr1 (\x acc -> x ++ "\n" ++ acc) board+ where line r = foldr (\x acc -> " " ++ (show x) ++ " " ++ acc) "" ( map ((!) b) r )+ board = [ line ( range ((i,1),(i,8)) ) | i <- [1..8]]+ tablerize b = column 1 $ " " ++ row ++ "\n" ++ b+ where row = foldr (\x acc -> " " ++ (show x) ++ " " ++ acc) "" [1..8]+ column i [] = []+ column i (x:xs)+ | x == '\n' = (x : (show i)) ++ (column (i+1) xs)+ | otherwise = (x : column i xs)++-- Make a 8-board with 4 centered pieces (othello rules)+makeBoard :: Board+makeBoard = board n // [((4,4), X), ((4,5), O), ((5,4), O), ((5,5), X)]+ where board n = array ((1,1), n) [ ((i,j), E) | (i,j) <- range ((1,1), n)]+ n = (8,8)++-- Adds or updates a given piece+move :: Board -> Move -> Board+move b (p, s) = b // [(p,s)]++moves :: Board -> [Move] -> Board+moves b mvs = b // mvs++-- Checks if some move is valid+check :: Board -> Move -> Bool+check b m = empty b p && (foldr (||) False (map hasChain (allChains newBoard p)))+ where newBoard = move b m+ p = fst m++-- Turns out all flankered pieces+flipChains :: Board -> Position -> Board+flipChains b p = foldr (\x bacc -> if hasChain x then moves bacc $ turnChain x else bacc) b chains+ where chains = allChains b p+ turnChain ps = map turnPiece $ takeWhile (\x -> current /= snd x ) (tail ps)+ turnPiece (p,s)+ | s == O = (p,X)+ | otherwise = (p,O)+ current = b!p++-- Finds the all 8 possible chains for a given position+allChains :: Board -> Position -> [[(Position, State)]]+allChains b p = map (slice b p) [(-1,0),(-1,1),(0,1),(1,1),(1,0),(1,-1),(0,-1),(-1,-1)]++-- Check if there are a chain of pieces other than the first one+hasChain :: [(Position, State)] -> Bool+hasChain ((m,s):ms) = hasChainOf s ms 0+ where hasChainOf _ [] _ = False+ hasChainOf sym (x:xs) pos+ | snd x == sym = pos /= 0+ | snd x /= E = hasChainOf sym xs (pos+1)+ | otherwise = False++slice :: Board -> Position -> (Int,Int) -> [(Position, State)]+slice b (i,j) (di,dj)+ | inRange (bounds b) (i,j) = (current : slice b (i+di,j+dj) (di,dj))+ | otherwise = []+ where current = ((i,j), b!(i,j))++-- Checks if there is at least one valid move for the given state+hasMovesFor :: Board -> State -> Bool+hasMovesFor b s = foldr1 (||) moves+ where moves = [ check b ((i,j),s) | (i,j) <- range (bounds b) ]++-- Verifies if a given position is empty+empty :: Board -> Position -> Bool+empty b p = (b!p) == E++-- All possible indexes for the board+indexes :: Board -> [(Int,Int)]+indexes b = range (bounds b)++-- Current state of given position+value :: Board -> Position -> State+value b p = b!p
+ DataTypes.hs view
@@ -0,0 +1,11 @@+module DataTypes where++import Data.Array++-- Possible states of a given point in a board+data State = X | O | E+ deriving (Eq, Show, Read)++type Board = Array (Int,Int) State+type Position = (Int,Int)+type Move = (Position, State)
reversi.cabal view
@@ -7,7 +7,7 @@ -- The package version. See the Haskell package versioning policy -- (http://www.haskell.org/haskellwiki/Package_versioning_policy) for -- standards guiding when and how versions should be incremented.-Version: 0.1+Version: 0.1.1 -- A short (one-line) description of the package. Synopsis: Text-only reversi (aka othelo) game@@ -37,7 +37,7 @@ -- Extra files to be distributed with the package, such as examples or -- a README.--- Extra-source-files:+Extra-source-files: Board.hs, DataTypes.hs -- Constraint on the version of Cabal needed to build this package. Cabal-version: >=1.4