作为学习Haskell的一种方法,我决定制作扫雷克隆。我已经写了一些代码,程序的主要结构已经准备就绪。它基于:
Board
,其中包含amount
个地雷,fields
以及地图的width
和height
列表。Field
,包含相邻地雷的数量或表示该地块本身就是地雷的值。 Field
还包含FieldState
(Marked
,Hidden
或Shown
)。游戏循环如下所示:
play board = do
-- Clear the screen
putStrLn $ replicate 40 '\n'
-- Show the board
print board
-- Get and process user input
putStr "Command: "
-- We are generating a new board to reflect the changes!
newBoard <- parseInput board <$> getLine
-- If the game is not ended, go to next step
if gameEnded newBoard
then return $ result newBoard
else play newBoard
现在效果非常好,但我不喜欢这样一个事实,即每次转弯后我都必须生成一个新的Board
。从像C ++这样的命令式语言来看,它看起来效率低下,你只需要改变现有的电路板。
重点:
答案 0 :(得分:4)
你当然是对的,完全更换电路板不是最佳的,但它并不一定像你想象的那么糟糕。如果Board
使用[[FieldState]]
- 2D网格,那么更新单个单元实际上会重新使用大部分行(这可以不用考虑而且完全安全,因为 Haskell纯粹是功能性的:对于 n × n 网格,复杂性是 O ( n ),只有一个常量比起查找任何给定字段所需的因素更糟糕。对于像扫雷这样的游戏来说,绝对不会有任何问题。
对于性能更关键的内容,有专门的数组类型可以同时查找和更新 O 中的单个字段(IO
或ST
monad) (1)。对于类似于你的应用程序,Data.Array.MArray
可能是最合适的(尽管社区中存在某种趋势,而是在较低级别,更优化的vector类型周围编写您的抽象。)< / p>