Ho cercato di imparare Haskell in modo indipendente nelle ultime settimane. Attualmente, sto cercando di implementare un piccolo gioco indovinato in cui il computer sceglie un numero casuale e l'utente prova a indovinarlo. Se l'utente ha torto, il programma dice all'utente che la risposta è più alta o più bassa e consente all'utente di indovinare fino a quando non lo indovinano correttamente. Ho funzionato, ma vorrei aggiungere la possibilità di tenere traccia del numero di ipotesi che l'utente fa ogni gioco e riportare quel numero all'utente una volta che lo indovino correttamente.Come tenere traccia del numero di ipotesi in un semplice gioco di ipotesi (Haskell)
Provenendo da uno sfondo imperativo, la cosa naturale da fare sarebbe avere un contatore che viene incrementato ogni volta che l'utente fa un'ipotesi, ma non è possibile farlo in Haskell (almeno sembra l'apolidia e l'immutabilità di tutto lo impedirebbe).
Mi sono divertito con l'idea di rendere le funzioni getGuess e giveHints un parametro aggiuntivo che rappresenta il numero di ipotesi finora (chiamiamolo numGuesses) e, ad ogni chiamata a quei metodi, pass (numGuesses + 1) . Ma non riuscivo a farlo funzionare (per non parlare che non so nemmeno se funzionasse).
Il mio codice è di sotto. Qualsiasi suggerimento sarebbe molto apprezzato. Sono principalmente alla ricerca di idee, ma sentitevi liberi di pubblicare anche il codice attuale. Inoltre, non esitate a farmi sapere se il mio codice fa schifo e come potrei migliorare se si nota qualcosa di atroce
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
Nota (ho solo la programmazione funzionale per un paio di settimane!): Io sto usando hFlush stdout perché sto usando il buffering di riga e, senza di esso, l'ordine di alcune interazioni non è quello che ci si aspetterebbe.
La tua idea (aggiungendo un parametro che conta quanti errori sono già passati) è perfetta. Cosa è andato storto quando lo hai provato? –
Mi piacerebbe indirizzare un bit strano in questo codice che non è correlato alla domanda reale (motivo per cui questo è un commento separato). Se stai usando un seed esplicito, dovresti rimettere il nuovo seme restituito da 'randomR' usando' setStdGen' invece di eseguire nuovamente il seeding con 'newStdGen'. (In effetti, in un mondo ideale, non avresti mai fatto un seeding, invece salvando il seed attraverso diverse sequenze del programma. Chiedimi perché se sei interessato.) In alternativa, puoi saltare il 'getStdGen/randomR/setStdGen 'sequenza usando' randomRIO', che incapsula questo pattern. –
Sono interessato. Perché? ;-) –