/
numguess.hs
71 lines (62 loc) · 2.41 KB
/
numguess.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
import System.IO
import System.Random
getName s = if length s == 0 then "Player" else s
getLimit :: String -> Int
getLimit [] = 10
getLimit s = max 10 (fst (readNumber s))
readNumber :: String -> (Int, Bool)
readNumber [] = (0, False)
readNumber s = if length r == 0 then readNumber [] else (fst (head r), True)
where r = reads s :: [(Int, String)]
evaluate :: (Int, Bool) -> Int -> Int -> (String, Int, Bool)
evaluate (guess, valid) num limit
| not valid = ("That's just plain wrong.", 0, False)
| num < 1 || num > limit = ("Out of range.", 0, False)
| guess < num = ("Too low!", 1, False)
| guess > num = ("Too high!", 1, False)
| guess == num = ("", 1, True)
customMessage :: Int -> Int -> String
customMessage tries limit
| tries == 1 = "You're one lucky bastard!"
| tries < maxTries = "You are the master of this game!"
| tries == maxTries = "You are a machine!"
| tries <= maxTries10 = "Very good result!"
| tries <= limit = "Try harder, you can do better!"
| otherwise = "I find your lack of skill disturbing!"
where maxTries = floor (logBase 2 (fromIntegral limit)) + 1
maxTries10 = floor (fromIntegral maxTries * 1.1)
playAgain :: String -> Bool
playAgain input
| input == "Y" || input == "y" = True
| otherwise = False
main = do
hSetBuffering stdout NoBuffering
putStr "Welcome to NumGuess Haskell version!\n\nEnter your name: "
input <- getLine
let name = getName input
putStr ("\nWelcome " ++ name ++ ", enter upper limit: ")
input <- getLine
let limit = getLimit input
play name limit
play name limit = do
putStrLn ("\nGuess my number between 1 and " ++ show limit ++ "!\n")
num <- randomRIO (1, limit)
guess name limit num 0
putStr "Play again [y/N]? "
input <- getLine
if playAgain input then
play name limit
else
putStrLn "\nOkay, bye."
guess name limit num tries = do
putStr "Guess: "
input <- getLine
let (message, add, finished) = evaluate (readNumber input) num limit
putStrLn message
if not finished then
guess name limit num (tries + add)
else do
let t = tries + add
putStr ("Well done " ++ name ++ ", you guessed my number from " ++ show t ++ " ")
putStrLn (if t == 1 then "try!" else "tries!")
putStrLn (customMessage t limit)