检查二维数组中的邻居时出错
Error with checking for neighbors in 2d array
我正在尝试在 Haskell 中为 class 实现 Conway 的游戏,并且有看起来像这样的代码来检查大小为 ( w,h):
liveNeighbors :: ((Int,Int), [[Bool]]) -> (Int,Int) -> Int
liveNeighbors arr@((w,h), cells) (x,y) =
let
j = w -1
k = h - 1
checkcell (x,y) = if (cells !! y) !! x then 1 else 0 in
case (x,y) of
-- Check right, bottom, and bottom right
(0,0) -> checkcell (x,y+1) + checkcell (x+1,y) + checkcell (x+1,y+1)
-- Check bottom, left, right, bottom left, bottom right
(_,0) -> checkcell (x,y+1) + checkcell (x-1,y) + checkcell (x+1,y)
+ checkcell (x+1,y+1) + checkcell (x-1,y+1)
-- check bottom, top, right, top right, bottom right
(0,_) -> checkcell (x,y+1) + checkcell (x,y-1) + checkcell (x+1,y)
+ checkcell (x+1,y+1) + checkcell (x+1,y-1)
-- check top, left, right,top left, top right
(_, k) -> checkcell (x,y-1) + checkcell (x-1,y) + checkcell (x+1,y)
+ checkcell (x-1,y-1) + checkcell (x+1,y-1)
-- check bottom, top, left, top left, bottom left
(j, _) -> checkcell (x,y+1) + checkcell (x,y-1) + checkcell (x-1,y)
+ checkcell (x-1,y+1) + checkcell (x-1,y-1)
-- check top, left, top left
(j,k) -> checkcell (x,y-1) + checkcell (x-1,y) + checkcell (x-1,y-1)
-- check bottom, left, bottom left
(j,0) -> checkcell (x,y+1) + checkcell (x-1,y) + checkcell (x-1,y+1)
-- check top, top right, right
(0,k) -> checkcell (x,y-1) + checkcell (x+1,y-1) + checkcell (x+1,y)
-- check all surrounding
(_,_) -> checkcell (x,y+1) + checkcell (x,y-1) + checkcell (x+1,y)
+ checkcell (x-1,y) + checkcell (x+1,y+1) + checkcell (x+1,y-1)
+ checkcell (x-1,y+1) + checkcell (x-1,y-1)
我正在使用 j
和 k
来适应数组的边界。我正在检查所有边缘情况和角落,但是代码在 (_, max_row)
、(max_column, _)
、(max_column, max_row)
处的数组大小和行失败并给出了不正确的值。这是 ghci 给我的输出:
> world = ((3,3), [[False, False, False], [False, False, False], [False, True,True]])
> liveNeighbors world (2,2)
*** Exception: Prelude.!!: index too large
> liveNeighbors world (0,2)
*** Exception: Prelude.!!: index too large
> liveNeighbors world (0,1)
1
> liveNeighbors world (1,1)
0
(1,1)
的值应该为 2,因为底部和右下角为真,但它只给出值 1。知道为什么会这样吗?
我不是在寻找代码解决方案,如果有人可以从概念上指出我在错误的方向上的正确方向,将不胜感激。项目仅限于列表处理,因此不允许使用列表或元组以外的其他数据结构。
这段代码有两个问题:
模式顺序:在您的示例中,您在测试 (2,2)
位置的代码时收到错误消息。这是因为模式(_, k)
早于(j, k)
,所以你检查“上,左,右,左上,右上”,而不是你预期的“上,左,左上”
模式中的变量:模式(_, k)
与代码中(x, y)
的其他值成功匹配,下面的模式重叠.您只是将 k
分配给 y
,而不是比较它们
因此,您可以这样编写代码(我使用 MultiWayIf
扩展来与原始代码更加相似,但它只是语法糖):
{-# LANGUAGE MultiWayIf #-}
neighbors :: ((Int,Int), [[Bool]]) -> (Int,Int) -> Int
neighbors arr@((w,h), cells) (x,y) =
let
j = w -1
k = h - 1
checkcell (x,y) = if (cells !! y) !! x then 1 else 0 in
if
-- Check right, bottom, and bottom right
| (x, y) == (0,0) -> checkcell (x,y+1) + checkcell (x+1,y) + checkcell (x+1,y+1)
--check top, left, top left
| (x, y) == (j,k) -> checkcell (x,y-1) + checkcell (x-1,y) + checkcell (x-1,y-1)
--check bottom, left, bottom left
| (x, y) == (j,0) -> checkcell (x,y+1) + checkcell (x-1,y) + checkcell (x-1,y+1)
-- check top, top right, right
| (x, y) == (0,k) -> checkcell (x,y-1) + checkcell (x+1,y-1) + checkcell (x+1,y)
-- Check bottom, left, right, bottom left, bottom right
| y == 0 -> checkcell (x,y+1) + checkcell (x-1,y) + checkcell (x+1,y) + checkcell (x+1,y+1) + checkcell (x-1,y+1)
--check bottom, top, right, top right, bottom right
| x == 0 -> checkcell (x,y+1) + checkcell (x,y-1) + checkcell (x+1,y) + checkcell (x+1,y+1) + checkcell (x+1,y-1)
-- check top, left, right,top left, top right
| y == k -> checkcell (x,y-1) + checkcell (x-1,y) + checkcell (x+1,y) + checkcell (x-1,y-1) + checkcell (x+1,y-1)
-- check bottom, top, left, top left, bottom left
| x == j -> checkcell (x,y+1) + checkcell (x,y-1) + checkcell (x-1,y) + checkcell (x-1,y+1) + checkcell (x-1,y-1)
--check all surrounding
| otherwise -> checkcell (x,y+1) + checkcell (x,y-1) + checkcell (x+1,y) + checkcell (x-1,y) + checkcell (x+1,y+1) +checkcell (x+1,y-1) + checkcell (x-1,y+1) + checkcell (x-1,y-1)
我正在尝试在 Haskell 中为 class 实现 Conway 的游戏,并且有看起来像这样的代码来检查大小为 ( w,h):
liveNeighbors :: ((Int,Int), [[Bool]]) -> (Int,Int) -> Int
liveNeighbors arr@((w,h), cells) (x,y) =
let
j = w -1
k = h - 1
checkcell (x,y) = if (cells !! y) !! x then 1 else 0 in
case (x,y) of
-- Check right, bottom, and bottom right
(0,0) -> checkcell (x,y+1) + checkcell (x+1,y) + checkcell (x+1,y+1)
-- Check bottom, left, right, bottom left, bottom right
(_,0) -> checkcell (x,y+1) + checkcell (x-1,y) + checkcell (x+1,y)
+ checkcell (x+1,y+1) + checkcell (x-1,y+1)
-- check bottom, top, right, top right, bottom right
(0,_) -> checkcell (x,y+1) + checkcell (x,y-1) + checkcell (x+1,y)
+ checkcell (x+1,y+1) + checkcell (x+1,y-1)
-- check top, left, right,top left, top right
(_, k) -> checkcell (x,y-1) + checkcell (x-1,y) + checkcell (x+1,y)
+ checkcell (x-1,y-1) + checkcell (x+1,y-1)
-- check bottom, top, left, top left, bottom left
(j, _) -> checkcell (x,y+1) + checkcell (x,y-1) + checkcell (x-1,y)
+ checkcell (x-1,y+1) + checkcell (x-1,y-1)
-- check top, left, top left
(j,k) -> checkcell (x,y-1) + checkcell (x-1,y) + checkcell (x-1,y-1)
-- check bottom, left, bottom left
(j,0) -> checkcell (x,y+1) + checkcell (x-1,y) + checkcell (x-1,y+1)
-- check top, top right, right
(0,k) -> checkcell (x,y-1) + checkcell (x+1,y-1) + checkcell (x+1,y)
-- check all surrounding
(_,_) -> checkcell (x,y+1) + checkcell (x,y-1) + checkcell (x+1,y)
+ checkcell (x-1,y) + checkcell (x+1,y+1) + checkcell (x+1,y-1)
+ checkcell (x-1,y+1) + checkcell (x-1,y-1)
我正在使用 j
和 k
来适应数组的边界。我正在检查所有边缘情况和角落,但是代码在 (_, max_row)
、(max_column, _)
、(max_column, max_row)
处的数组大小和行失败并给出了不正确的值。这是 ghci 给我的输出:
> world = ((3,3), [[False, False, False], [False, False, False], [False, True,True]])
> liveNeighbors world (2,2)
*** Exception: Prelude.!!: index too large
> liveNeighbors world (0,2)
*** Exception: Prelude.!!: index too large
> liveNeighbors world (0,1)
1
> liveNeighbors world (1,1)
0
(1,1)
的值应该为 2,因为底部和右下角为真,但它只给出值 1。知道为什么会这样吗?
我不是在寻找代码解决方案,如果有人可以从概念上指出我在错误的方向上的正确方向,将不胜感激。项目仅限于列表处理,因此不允许使用列表或元组以外的其他数据结构。
这段代码有两个问题:
模式顺序:在您的示例中,您在测试
(2,2)
位置的代码时收到错误消息。这是因为模式(_, k)
早于(j, k)
,所以你检查“上,左,右,左上,右上”,而不是你预期的“上,左,左上”模式中的变量:模式
(_, k)
与代码中(x, y)
的其他值成功匹配,下面的模式重叠.您只是将k
分配给y
,而不是比较它们
因此,您可以这样编写代码(我使用 MultiWayIf
扩展来与原始代码更加相似,但它只是语法糖):
{-# LANGUAGE MultiWayIf #-}
neighbors :: ((Int,Int), [[Bool]]) -> (Int,Int) -> Int
neighbors arr@((w,h), cells) (x,y) =
let
j = w -1
k = h - 1
checkcell (x,y) = if (cells !! y) !! x then 1 else 0 in
if
-- Check right, bottom, and bottom right
| (x, y) == (0,0) -> checkcell (x,y+1) + checkcell (x+1,y) + checkcell (x+1,y+1)
--check top, left, top left
| (x, y) == (j,k) -> checkcell (x,y-1) + checkcell (x-1,y) + checkcell (x-1,y-1)
--check bottom, left, bottom left
| (x, y) == (j,0) -> checkcell (x,y+1) + checkcell (x-1,y) + checkcell (x-1,y+1)
-- check top, top right, right
| (x, y) == (0,k) -> checkcell (x,y-1) + checkcell (x+1,y-1) + checkcell (x+1,y)
-- Check bottom, left, right, bottom left, bottom right
| y == 0 -> checkcell (x,y+1) + checkcell (x-1,y) + checkcell (x+1,y) + checkcell (x+1,y+1) + checkcell (x-1,y+1)
--check bottom, top, right, top right, bottom right
| x == 0 -> checkcell (x,y+1) + checkcell (x,y-1) + checkcell (x+1,y) + checkcell (x+1,y+1) + checkcell (x+1,y-1)
-- check top, left, right,top left, top right
| y == k -> checkcell (x,y-1) + checkcell (x-1,y) + checkcell (x+1,y) + checkcell (x-1,y-1) + checkcell (x+1,y-1)
-- check bottom, top, left, top left, bottom left
| x == j -> checkcell (x,y+1) + checkcell (x,y-1) + checkcell (x-1,y) + checkcell (x-1,y+1) + checkcell (x-1,y-1)
--check all surrounding
| otherwise -> checkcell (x,y+1) + checkcell (x,y-1) + checkcell (x+1,y) + checkcell (x-1,y) + checkcell (x+1,y+1) +checkcell (x+1,y-1) + checkcell (x-1,y+1) + checkcell (x-1,y-1)