import Control.Monad.State
import System.IO
import System.Random
gameLB, gameUB :: Integer
gameLB = 0
gameUB = 100
data GameState = GameState { steps :: Integer ,
lb :: Integer,
ub :: Integer }
initialState :: Integer -> Integer -> GameState
initialState l u = GameState { steps = 0, lb = l, ub = u }
updateState :: Integer -> Integer -> GameState -> GameState
updateState ans guess (GameState { steps = s, lb = l, ub = u }) =
case (compare ans guess) of
EQ -> GameState { steps = s + 1, lb = ans, ub = ans }
LT -> GameState { steps = s + 1, lb = l, ub = min (guess - 1) u }
GT -> GameState { steps = s + 1, lb = max l (guess + 1), ub = u }
range :: GameState -> (Integer, Integer)
range (GameState { lb = l, ub = u }) = (l , u)
stepCount :: GameState -> Integer
stepCount (GameState { steps = s }) = s
gameSession :: Integer -> StateT GameState IO Integer
gameSession ans =
do (l, u) <- gets range
lift $ putStr $ "Guess number (" ++ show l ++ ".." ++ show u ++ "): "
lift $ hFlush stdout
str <- lift $ getLine
let num = read str
modify (updateState ans num)
case (compare ans num) of
EQ -> gets stepCount >>= return
LT -> gameSession ans >>= return
GT -> gameSession ans >>= return
main :: IO ()
main = do rand <- getStdRandom (randomR (gameLB, gameUB))
s <- evalStateT (gameSession rand) (initialState gameLB gameUB)
putStrLn $ "Steps used: " ++ show s
備註:上面的程式用 ghc --make Guess.hs 就可以編譯了(有用到 mtl package)
沒有留言:
張貼留言