Advertisement
Guest User

Untitled

a guest
Feb 28th, 2023
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1.  
  2. module Main where
  3.  
  4. import System.Random (randomRIO)
  5. import System.IO (stdout, hSetBuffering, BufferMode (..))
  6. import Data.Char (isDigit, toLower, digitToInt)
  7. import Data.Functor ((<$))
  8. import Data.List (intercalate)
  9.  
  10. -- Assets
  11.  
  12. introText :: String
  13. introText = "\
  14. \Bagels, a deductive logic game.\n\
  15. \By Al Sweigart al@inventwithpython.com\n\
  16. \Haskell version by Liam Zhu\n\
  17. \\n\
  18. \I am thinking of a 3-digit number. Try to guess what it is.\n\
  19. \Here are some clues:\n\
  20. \When I say:    That means:\n\
  21. \ Pico         One digit is correct, but in the wrong position.\n\
  22. \ Fermi        One digit is correct, and in the right position.\n\
  23. \ Bagels       No digit is correct.\n"
  24.  
  25. gameStartText :: String
  26. gameStartText = "\
  27. \I have thought up a number.\n\
  28. \ You have 10 guesses to get it.\n"
  29.  
  30. -- end Assets
  31.  
  32. main :: IO ()
  33. main = do
  34.     hSetBuffering stdout NoBuffering
  35.     putStrLn introText
  36.     bagel
  37.  
  38. bagel :: IO ()
  39. bagel = do
  40.     putStrLn gameStartText
  41.     secretNumbers <- traverse (const $ randomRIO (0,9)) [1..3]
  42.     loopGuessesPrompt secretNumbers 1
  43.     newGamePrompt
  44.  
  45. loopGuessesPrompt :: [Int] -> Int -> IO ()
  46. loopGuessesPrompt [firstNumber, secondNumber, thirdNumber] 11 = do
  47.     putStrLn "You ran out of guesses."
  48.     putStrLn $ "The answer was "
  49.       <> (foldMap show [firstNumber, secondNumber, thirdNumber]) <> "."
  50. loopGuessesPrompt secretNumber n = do
  51.     putStrLn $ "Guess #" <> show n <> ":"
  52.     putStr "> "
  53.     getLine >>= loopEvaluateLine n secretNumber
  54.  
  55. loopEvaluateLine :: Int -> [Int] -> String -> IO ()
  56. loopEvaluateLine triesSoFar secretNumber guess
  57.     | 3 /= length guess || any (not . isDigit) guess =
  58.         loopGuessesPrompt secretNumber triesSoFar
  59.     | convertedNumber == ["Fermi", "Fermi", "Fermi"] =
  60.         putStrLn "You got it!"
  61.     | null $ concat convertedNumber = putStrLn "Bagels" >> loopGuessesPrompt secretNumber (succ triesSoFar)
  62.     | otherwise =
  63.         putStrLn (intercalate " " (filter (not . null) convertedNumber)) >> loopGuessesPrompt secretNumber (succ triesSoFar)
  64.   where
  65.     parsedGuess = digitToInt <$> guess
  66.    
  67.     convertedNumber =
  68.         fermis <> picos
  69.  
  70.     fermis = "Fermi" <$ filter (\(a,b) -> a == b) groups
  71.  
  72.     groups = zip parsedGuess secretNumber
  73.  
  74.     picos  = "Pico" <$ filter (\(a,b) -> a /= b && a `elem` secretNumber) groups
  75.  
  76. newGamePrompt :: IO ()
  77. newGamePrompt = do
  78.     putStrLn "Do you want to play again? (yes or no)"
  79.     putStr "> "
  80.     fmap toLower <$> getLine >>= \case
  81.         'y':xs -> bagel
  82.         _ -> pure ()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement