【发布时间】:2019-07-26 00:05:26
【问题描述】:
我是 Haskell 的新手,我一直在编写一个简单的刽子手游戏来适应这种语言。我将游戏状态存储在名为 GameState 的数据类型中。
data GameState = GameState
{ word :: String,
blanks :: String,
wrongGuesses :: [Char]
} deriving Show
我还有一个函数可以更新输入字符的状态,还有一个函数可以检查游戏是否结束。
updateState :: GameState -> Char -> GameState
updateState state c
| (c `elem` (word state)) = state { blanks = newBlanks }
| otherwise = state { wrongGuesses = c:(wrongGuesses state)}
where newBlanks = foldr replaceAt (blanks state) $ elemIndices c (word state)
replaceAt i = (take i) <> (const [c]) <> (drop (i + 1))
isPlaying :: GameState -> Bool
isPlaying state = ('_' `elem` (blanks state)) && (length (wrongGuesses state) < 5)
给定一个字符列表,我可以折叠来模拟给定输入的游戏。
runGame :: GameState -> [Char] -> [GameState]
runGame initialState chars = takeWhile isPlaying $ scanl updateState initialState chars
我的问题是如何调整此代码以处理实际用户输入。我尝试过使用序列,但程序只是无休止地获取用户输入。
main = runGame (newState "secret") <$> (sequence $ repeat getChar)
有什么方法可以折叠 getChar 类似于 runGame 的工作原理并在每次用户输入后打印游戏状态?我想避免像 runGame 那样的显式递归,如果可能的话,我想坚持使用标准库函数。
【问题讨论】: