我以为我在Haskell研究中一帆风顺,直到......
我有一个[[Int]]
tiles = [[1,0,0]
,[0,1,0]
,[0,1,0]
]
Run Code Online (Sandbox Code Playgroud)
和数据类型:
data Coord = Coord
{ x :: Int
, y :: Int
} deriving (Eq)
Run Code Online (Sandbox Code Playgroud)
基于输入tiles,我一直在尝试输出a [Coord],这样Coord只有当值为tiles1 时才生成a ,并且Coord它将在2d列表中存储它的位置:
blackBox :: [[Int]] -> [Coord]
blackBox tiles = <magic>
-- given the above example I would expect:
-- [(Coord 0 0),(Coord 1 1),(Coord 1 2)]
Run Code Online (Sandbox Code Playgroud)
我尝试过第一次将[[Int]]转换为[Int],通过:
foldTiles :: [[Int]] -> [Int]
foldTiles tiles = foldr (++) [] tiles
Run Code Online (Sandbox Code Playgroud)
但在那之后,我不确定如何传递指数.我想如果我可以映射"折叠的瓷砖",输出一个元组(值,索引),我可以很容易地找出其余部分.
更新如果有人感兴趣,我得到它的工作,这里是它的演示(源代码和GitHub的链接)!我将不得不花更多的时间来理解每个答案,因为这是我第一次使用FP编写游戏.非常感谢!
http://kennycason.com/posts/2013-10-10-haskell-sdl-gameboy-boxxle.html
kqr*_*kqr 12
这是列表理解发光的地方.
blackBox tiles =
[Coord x y -- generate a Coord pair
| (y, row) <- enumerate tiles -- for each row with its coordinate
, (x, tile) <- enumerate row -- for each tile in the row (with coordinate)
, tile == 1] -- if the tile is 1
Run Code Online (Sandbox Code Playgroud)
或者您可以使用等效do符号(因为列表是monad),这需要导入Control.Monad(for guard.)
blackBox tiles = do
(y, row) <- enumerate tiles -- for each row with its coordinate
(x, tile) <- enumerate row -- for each tile in the row (with coordinate)
guard $ tile == 1 -- as long as the tile is 1
return $ Coord x y -- return a coord pair
Run Code Online (Sandbox Code Playgroud)
为了帮助理解,后一个函数的工作方式类似于以下Python函数.
def black_box(tiles):
for y, row in enumerate(tiles):
for x, tile in enumerate(row):
if tile == 1:
yield Coord(x, y)
Run Code Online (Sandbox Code Playgroud)
do 列表monad的表示法对于处理列表非常方便,我认为,所以值得环顾四周!
在这两个例子中,我都使用了这个定义
enumerate = zip [0..]
Run Code Online (Sandbox Code Playgroud)