言語は実際にプログラムを書いてみないと身に付かない。ということで、昔、ポケコンでよく見かけた数あてゲームをHaskellで書いてみた。
コンピュータが生成した数字をあてる。
コンピュータは、予想した数に対して
Hit: 数字はあっているが、場所が異なる数字の数
Blow:数字も場所もあっている数字の数
の2種類のヒントを返す
import System.Random
import Control.Monad(when)
isUsedNum :: Char->String->Int
isUsedNum _ [] = 0
isUsedNum a (x:xs)
| a == x = 1 + isUsedNum a xs
| otherwise = isUsedNum a xs
countUsedNum :: String->String->Int
countUsedNum [] _ = 0
countUsedNum (x:xs) ys = isUsedNum x ys + countUsedNum xs ys
countBlow :: String->String->Int
countBlow [] _ = 0
countBlow _ [] = 0
countBlow (x:xs) (y:ys)
| x == y = 1 + countBlow xs ys
| otherwise = countBlow xs ys
resultString :: String->String->(Bool, String)
resultString xs ys =
(endFlag, show hit ++ " hit(s) "
++ show blow ++ " blow(s).")
where blow = countBlow xs ys
hit = countUsedNum xs ys - blow
endFlag = blow == 4
isSuitableNum :: String->Bool
isSuitableNum [] = True
isSuitableNum (x:xs) = isUsedNum x xs == 0 && isSuitableNum xs
checkNum :: String->IO ()
checkNum compNum = do
putStr "Number ? "
guessNum <- getLine
when (not $ null guessNum) $ do
let (flag, msg) = resultString compNum guessNum
putStrLn msg
when (not flag) $ checkNum compNum
return ()
targetNum :: [Int]->String
targetNum (x:xs)
| (isSuitableNum strX) = strX
| otherwise = targetNum xs
where strX = show x
main = do
r <- getStdRandom $ randomR (0, 99)
let t = targetNum $ randomRs (0,9999) (mkStdGen r)
checkNum t
putStrLn t
乱数は
すごいHaskellたのしく学ぼう!
の通りにはいかなかった。パッケージングが変更になったんだそうだ。
cabal install random
としてパッケージを追加。また、使い方は
Random モジュールの使い方 : tnomuraのブログが参考になった。