我必须为 2048 实现一个游戏板。 我声明了:
type Board = [[Int]]
为了在随机单元格中添加新的随机值,我必须检查该单元格中的值,但我不知道如何获取该值。我见过使用 monad 的不同示例,但我不知道如何使用 Monad
并且我想知道是否还有其他方法可以做到这一点。
谁能帮我举个例子吗?
谢谢!
最佳答案
嗯,至于检查特定单元格中的值 - 这只是列表索引,您可以简单地使用 !!
。由于列表是嵌套的,因此您需要两次查找,首先是行,然后是列/单元格。
type CellId = (Int,Int)
cellAt :: Board -> CellId -> Int
cellAt rows (idy, idx) = rows !! idy !! idx
我不太明显的是更新。要以函数式风格做到这一点,您需要一个类似的函数
updataCellAt :: CellId -> Int -> Board -> Board
它接受一个板作为参数,并返回一个修改后的板。
修改列表仅在一个位置很容易:头部。
replaceHead :: a -> [a] -> [a]
replaceHead _ [] = []
replaceHead x (_:xs) = x:xs
要修改任意位置,最好的办法是首先将该位置之前的所有内容拆分为列表,然后所有内容都在那里形成(因此第二个列表将该位置作为其头部)。
replaceAt :: Int -> a -> [a] -> [a]
replaceAt i x xs = let (prev, remain) = splitAt i xs
in prev ++ replaceHead x remain
现在,这不是很灵活:您只需丢弃替换的元素,但通常您可能只想对其应用转换。
modifyHead :: (a->a) -> [a] -> [a]
modifyHead _ [] = []
modifyHead mdf (x:xs) = mdf x : xs
modifyAt :: Int -> (a->a) -> [a] -> [a]
modifyAt i mdf xs = let (prev, remain) = splitAt i xs
in prev ++ modifyHead mdf remain
现在可以轻松地使用此列表来修改嵌套列表,例如您的面板:
modifyCellAt :: CellId -> (a->a) -> [[a]] -> [[a]]
modifyCellAt (iy, ix) mdf = modifyAt iy (\row -> modifyAt ix mdf row)
-- or short: modifyAt iy $ modifyAt ix mdf
关于haskell - 如何从Haskell矩阵中的某个位置提取值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23427728/