Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- module Main where
- import System.Random (randomRIO)
- import System.IO (stdout, hSetBuffering, BufferMode (..))
- import Data.Char (isDigit, toLower, digitToInt)
- import Data.Functor ((<$))
- import Data.List (intercalate)
- -- Assets
- introText :: String
- introText = "\
- \Bagels, a deductive logic game.\n\
- \By Al Sweigart al@inventwithpython.com\n\
- \Haskell version by Liam Zhu\n\
- \\n\
- \I am thinking of a 3-digit number. Try to guess what it is.\n\
- \Here are some clues:\n\
- \When I say: That means:\n\
- \ Pico One digit is correct, but in the wrong position.\n\
- \ Fermi One digit is correct, and in the right position.\n\
- \ Bagels No digit is correct.\n"
- gameStartText :: String
- gameStartText = "\
- \I have thought up a number.\n\
- \ You have 10 guesses to get it.\n"
- -- end Assets
- main :: IO ()
- main = do
- hSetBuffering stdout NoBuffering
- putStrLn introText
- bagel
- bagel :: IO ()
- bagel = do
- putStrLn gameStartText
- secretNumbers <- traverse (const $ randomRIO (0,9)) [1..3]
- loopGuessesPrompt secretNumbers 1
- newGamePrompt
- loopGuessesPrompt :: [Int] -> Int -> IO ()
- loopGuessesPrompt [firstNumber, secondNumber, thirdNumber] 11 = do
- putStrLn "You ran out of guesses."
- putStrLn $ "The answer was "
- <> (foldMap show [firstNumber, secondNumber, thirdNumber]) <> "."
- loopGuessesPrompt secretNumber n = do
- putStrLn $ "Guess #" <> show n <> ":"
- putStr "> "
- getLine >>= loopEvaluateLine n secretNumber
- loopEvaluateLine :: Int -> [Int] -> String -> IO ()
- loopEvaluateLine triesSoFar secretNumber guess
- | 3 /= length guess || any (not . isDigit) guess =
- loopGuessesPrompt secretNumber triesSoFar
- | convertedNumber == ["Fermi", "Fermi", "Fermi"] =
- putStrLn "You got it!"
- | null $ concat convertedNumber = putStrLn "Bagels" >> loopGuessesPrompt secretNumber (succ triesSoFar)
- | otherwise =
- putStrLn (intercalate " " (filter (not . null) convertedNumber)) >> loopGuessesPrompt secretNumber (succ triesSoFar)
- where
- parsedGuess = digitToInt <$> guess
- convertedNumber =
- fermis <> picos
- fermis = "Fermi" <$ filter (\(a,b) -> a == b) groups
- groups = zip parsedGuess secretNumber
- picos = "Pico" <$ filter (\(a,b) -> a /= b && a `elem` secretNumber) groups
- newGamePrompt :: IO ()
- newGamePrompt = do
- putStrLn "Do you want to play again? (yes or no)"
- putStr "> "
- fmap toLower <$> getLine >>= \case
- 'y':xs -> bagel
- _ -> pure ()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement