ここ数週間、Haskell を独学で学ぼうとしてきました。現在、コンピューターが乱数を選択し、ユーザーがそれを推測しようとする、ちょっと間抜けな推測ゲームを実装しようとしています。ユーザーが間違っている場合、プログラムはユーザーに答えが高いか低いかを伝え、ユーザーが正しく推測できるまで推測できるようにします。私はそれを機能させましたが、ユーザーがすべてのゲームで行った推測の数を追跡し、正しく推測したらその数をユーザーに報告する機能を追加したいと思います。
命令的なバックグラウンドから来ると、ユーザーが推測するたびにインクリメントされるカウンターを用意するのが自然なことですが、Haskell では実際にそれを行うことはできません (少なくとも、すべてのステートレス性と不変性のように思えます)。それを防ぎます)。
getGuess 関数と giveHints 関数に、これまでの推測の数を表す追加のパラメーター (これを numGuesses と呼びましょう) を取り、これらのメソッドを呼び出すたびに (numGuesses+1) を渡すというアイデアをいじりました。しかし、私はそれを機能させることができませんでした (言うまでもなく、それが機能するかどうかさえわかりません)。
私のコードは以下です。任意の提案をいただければ幸いです。私は主にアイデアを探していますが、実際のコードも自由に投稿してください。また、コードがうまくいかない場合や、コードを改善する方法を教えてください。
import System.Random
import System.IO
import Control.Monad
main = do
gen <- getStdGen
let (ans,_) = randomR (1,100) gen :: (Int,StdGen)
putStrLn $ "I'm thinking of a number between 1 and 100..."
getGuess ans
putStrLn "You guessed it in __ guesses!"
putStr "Play again? "
hFlush stdout
desire <- getLine
when ((desire !! 0) `elem` ['y','Y']) $ do
putStrLn ""
newStdGen
main
getGuess ans = do
putStr "Your guess? "
hFlush stdout
guessStr <- getLine
giveHints ans (read guessStr)
giveHints ans guess = do
when (ans /= guess) $ do
if ans > guess
then putStrLn "It's higher."
else putStrLn "It's lower."
getGuess ans
注: ライン バッファリングを使用しているため、hFlush stdout を使用しています。これがないと、一部の相互作用の順序が期待どおりにならないことがあります。