2012/07/29

Haskellで数あてゲームを書いてみる

言語は実際にプログラムを書いてみないと身に付かない。ということで、昔、ポケコンでよく見かけた数あてゲームを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のブログが参考になった。



0 件のコメント :

コメントを投稿

Comments on Google+: