Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Helge Mikael Landro
- import Data.Char
- {-
- For simplicity the player number is
- represented as an integer (1 or 2).
- -}
- next :: Int -> Int
- next 1 = 2
- next 2 = 1
- {-
- In turn, we represent the board as a list
- comprising the number of stars that remain
- on each row, with the initial board given by
- the list [5,4,3,2,1] and the game being finished
- when all rows have no stars left.
- -}
- type Board = [Int]
- initial :: Int -> Board
- initial rows = if rows == 2 then [1,2]
- else if rows == 3 then [1,2,3]
- else if rows == 4 then [1,2,3,4]
- else if rows == 5 then [1,2,3,4,5]
- else error "wrong input"
- finished :: Board -> Bool
- finished = all (== 0)
- {-
- A move in the game is specified by a row number
- and the number of stars to be removed, and is valid
- if the row contains at least this many stars.
- Example:
- -- The first row on the initial board contains at least 3 stars
- > valid initial 1 3
- True
- -- The 4th row contains fewer than 3 stars
- > valid inital 4 3
- False
- -}
- valid :: Board -> Int -> Int -> Bool
- valid board row num = (row - 1) >= num
- {-
- A valid move can then be applied to a board to
- give a new board by using a list comprehension
- to update the number of stars taht remain in
- each row.
- Example:
- -- 3 stars have been removed in the 1 row
- > move inital 1 3
- [2,4,3,2,1]
- -}
- move :: Board -> Int -> Int -> Board
- move board row num = [update r n | (r, n) <- zip [1..] board]
- where update r n = if r == row then (n - num) else n
- -- IO Utils
- putRow :: Int -> Int -> IO ()
- putRow row num = do putStr (show num ++ " ")
- putStrLn (concat (replicate num " * "))
- putColumn :: Int -> IO()
- putColumn num = do putStr " "
- putStr (show (num))
- putBoard :: Board -> Int -> IO ()
- putBoard board rows = if length board == 2 then do
- putRow 1 1
- putRow 2 2
- putColumn rows
- else if length board == 3 then do
- putRow 1 1
- putRow 2 2
- putRow 3 3
- putColumn rows
- else if length board == 4 then do
- putRow 1 1
- putRow 2 2
- putRow 3 3
- putRow 4 4
- putColumn rows
- else if length board == 5 then do
- putRow 1 1
- putRow 2 2
- putRow 3 3
- putRow 4 4
- putRow 5 5
- putColumn rows
- else error "Fix"
- getDigit :: String -> IO Int
- getDigit prompt = do putStr prompt
- x <- getChar
- newline
- if isDigit x then
- return (digitToInt x)
- else
- do putStrLn "ERROR: Invalid digit"
- getDigit prompt
- newline :: IO ()
- newline = putChar '\n'
- -- Game of nim
- play :: Board -> Int -> Int-> IO ()
- play board player rows = do
- putStrLn "n(im) x / c(homp) x / q(uit)"
- userInput <- getLine
- if head userInput == 'n' then putStrLn "Lets play nim bitches!"
- else if head userInput == 'c' then putStrLn "Chomp"
- else if head userInput == 'q' then do
- putStrLn "Now quitting the game."
- return ()
- else error "Invalid input"
- putBoard board rows
- if finished board then
- do newline
- putStr "Player "
- putStr (show (next player))
- putStrLn " wins!"
- else
- do newline
- putStr "Player "
- putStrLn (show player)
- row <- getDigit "Enter a row number: "
- num <- getDigit "Stars to remove: "
- if valid board row num then
- play (move board row num) (next player) rows
- else
- do newline
- putStrLn "ERROR: Invalid move"
- play board player rows
- nim :: Int -> IO ()
- nim num = play (initial num) 1 num
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement