-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathchapter10_nim.hs
83 lines (66 loc) · 2.14 KB
/
chapter10_nim.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import Data.Char
next :: Int -> Int
next 1 = 2
next 2 = 1
type Board = [Int]
initial :: Board
initial = [5, 4, 3, 2, 1]
finished :: Board -> Bool
finished = all (== 0)
valid :: Board -> Int -> Int -> Bool
valid board row num = board !! (row - 1) >= num
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
putRow :: Int -> Int -> IO ()
putRow row num = do putStr (show row)
putStr ": "
putStrLn (concat (replicate num "* "))
putBoard :: Board -> IO ()
--putBoard [a, b, c, d, e] = do putRow 1 a
-- putRow 2 b
-- putRow 3 c
-- putRow 4 d
-- putRow 5 e
--hw10 2
--putBoard b = putBoardAux (zip [1..] b)
--putBoardAux [] = return ()
--putBoardAux ((r, n):xs) = do putRow r n
-- putBoardAux xs
--
--hw10 3
putBoard b = sequence_ [putRow r n | (r, n) <- zip [1..] b]
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'
play :: Board -> Int -> IO ()
play board player =
do newline
putBoard board
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)
else
do newline
putStrLn "ERROR: Invalid move"
play board player
nim :: IO ()
nim = play initial 1