如何解决Ocaml 中的“熄灯”游戏、数组和异常处理
练习是这样给出的:
- 创建一个函数翻转 val 翻转:bool 数组数组 -> int -> int -> bool 数组数组 = 给定一个布尔矩阵和两个整数 i,j。它否定了这些值 (true→false,false→true) 在矩阵中的位置 i,j,以及否定 (最多)4 个水平/垂直相邻元素上的值。
这是我的功能:
let flip m a b=
for i=0 to ((Array.length m)-1) do
for j=0 to ((Array.length m.(1))-1) do
if i=a && j=b then
begin
m.(i).(j) <- not m.(i).(j);
try m.(i-1).(j) <- not m.(i-1).(j) with (Invalid_argument "index out of bounds") -> ();
try m.(i).(j-1) <- not m.(i).(j-1) with (Invalid_argument "index out of bounds") -> ();
try m.(i+1).(j) <- not m.(i+1).(j) with (Invalid_argument "index out of bounds") -> ();
try m.(i).(j+1) <- not m.(i).(j+1) with (Invalid_argument "index out of bounds") -> ();
end;
done;
done;
m;;
当我向这个函数提供任何类型的 2d bool 数组时,我会返回相同的数组,而没有对其进行任何更改。我做错了什么,我没看到?
解决方法
你做错了什么是你的问题,因为你的函数虽然不完美,但至少改变了输入数组并返回它,例如,
# let x = Array.create_matrix 3 3 true;;
val x : bool array array =
[|[|true; true; true|]; [|true; true; true|]; [|true; true; true|]|]
# flip x 1 1;;
- : bool array array =
[|[|true; false; true|]; [|true; false; true|]; [|true; true; true|]|]
因此,如您所见,某些值发生了翻转。正如我们从评论部分看到的,您创建了一个 3x4 矩阵(3 行 4 列),然后要求更改索引为 (1,4) 的元素,该元素对应于第二行和第五列,因为数组是在 OCaml 中索引(以及从零开始的许多其他编程语言)。由于 j
始终小于 4(每个代码的范围从 0
到 Array.length(1) - 1
,即 0,1,2,3`,条件永远不会发生。但这又不是您的函数存在问题,但与调用您的函数有关。
不过,您的函数存在一些问题。
- 它不会复制输入数组,而是在原地对其进行变异,有关详细信息,请参阅 this question
- 您正在捕获异常,而最好使用循环来否定“(最多)4 个水平/垂直相邻的元素”。你的方法可能会奏效,但它不能扩展,而且肯定不会得到很好的评分(提示,这不是你的老师希望你做的)。此外,在当前的实现中,它最多只改变 1 行和 1 列,因此为了使您的方法正常工作,您需要多三倍的代码行。不过,您可以尝试编写它们,因为它可能有助于您了解模式并将其转化为迭代。
- 当您捕获与错误消息永远不匹配的异常时,它会使您的代码变得脆弱,因为它取决于错误消息的实际内容(和语言)。你可以写
try m.(i-1).(j) <- not m.(i-1).(j) with _ -> ()
,至少它不那么冗长,更容易看到缺失的模式。 -
for j=0 to ((Array.length m.(1))-1) do
您将矩阵的第二行作为维度。如果您的矩阵只有一行,并且通常对于不是矩阵的数组数组,即每行具有不同数量的元素,则它将不起作用。执行for j=0 to Array.length m.(i) - 1 do
更好,更健壮,例如,使用当前i
-th 行的长度。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。