我无法弄清楚 if 语句有问题。
我的代码:
type chess_board = char array array;;
type position = int * int;;
let chess_board_1:chess_board = [|
[|' ';' ';' ';' ';' ';' ';' ';' '|];
[|' ';' ';' ';' ';' ';' ';' ';' '|];
[|' ';' ';' ';' ';' ';' ';' ';' '|];
[|' ';' ';' ';' ';' ';' ';' ';' '|];
[|' ';' ';' ';' ';' ';' ';' ';' '|];
[|' ';' ';' ';' ';' ';' ';' ';' '|];
[|' ';' ';' ';' ';' ';' ';'Q';' '|];
[|' ';' ';' ';' ';' ';' ';' ';' '|];
|];;
let queen_targeting (chess:chess_board) pos =
match pos with
|(x0, y0) ->
for y = 0 to Array.length chess -1 do
for x = 0 to Array.length chess.(y) -1 do
if chess.(y).(x) = 'Q'
then
if (
x = x0 || (* Check horizontaly *)
y = y0 || (* Check verticaly *)
x - x0 = y - y0 (* Check diagonaly *)
)
then true
else false
done
done
;;
queen_targeting chess_board_1 (3, 3);; (* Expected true *)
我收到此错误消息:
File "[32]", line 27, characters 25-29:
Error: This variant expression is expected to have type unit
The constructor true does not belong to type unit
Characters 874-878:
then true
我不知道这意味着什么。我测试了 if 语句在其他方法中返回 true/false,效果很好。我不知道为什么它在这种情况下不起作用,所以如果有人可以提供帮助,请这样做。
更实用的解决方案是使用
Array.iteri
:
let queen_targeting (chess:chess_board) (x0,y0) =
let exception Return of bool in
let threat y x case =
if case = 'Q' && (x = x0 || y = y0 || x - x0 = y - y0) then
raise (Return true)
in
match Array.iteri (fun y -> Array.iteri (threat y)) chess with
| () -> false
| exception Return b -> b
这里的异常用于当我们发现女王瞄准该位置时立即返回。
“for 表达式”必须返回
unit
,因此结果不会传播。例如:
# let x = for y = 0 to 10 do true done;;
潜在客户发出此警告:
Warning 10: this expression should have type unit.
val x : unit = ()
解决方案是使用可变引用:
type chess_board = char array array;;
type position = int * int;;
let chess_board_1:chess_board = [|
[|' ';' ';' ';' ';' ';' ';' ';' '|];
[|' ';' ';' ';' ';' ';' ';' ';' '|];
[|' ';' ';' ';' ';' ';' ';' ';' '|];
[|' ';' ';' ';' ';' ';' ';' ';' '|];
[|' ';' ';' ';' ';' ';' ';' ';' '|];
[|' ';' ';' ';' ';' ';' ';' ';' '|];
[|' ';' ';' ';' ';' ';' ';'Q';' '|];
[|' ';' ';' ';' ';' ';' ';' ';' '|];
|];;
let queen_targeting (chess:chess_board) pos =
match pos with
|(x0, y0) ->
let result = ref false in
for y = 0 to Array.length chess -1 do
for x = 0 to Array.length chess.(y) -1 do
if chess.(y).(x) = 'Q'
then
if (
x = x0 || (* Check horizontaly *)
y = y0 || (* Check verticaly *)
x - x0 = y - y0 (* Check diagonaly *)
)
then result := true
else result := false
done
done;
false || !result
;;
queen_targeting chess_board_1 (3, 3);;
其他答案已经解决了您迫在眉睫的问题,但是有一些机会可以解决代码中不适合发表评论的问题。希望这些建议能够消除无关的噪音,让您将来更容易推理代码。
这听起来有些迂腐,但请记住 OCaml 中没有条件语句。相反,它们是具有值的表达式。我怀疑您已经明白这一点,但术语很重要。
此外,条件语句的使用方式也存在一些问题。如果您唯一要做的就是返回 true 或 false,那么只需直接使用布尔表达式即可。考虑一个简单的例子。
if a < b && b < c then true else false
这与:
没有什么不同a < b && b < c
第三,当您有嵌套条件时,通常可以简化它们。我将稍微修改一下您的代码并暂时删除注释。
if chess.(y).(x) = 'Q' then
if x = x0 || y = y0 || x - x0 = y - y0 then
true
else
false
我们知道我们可以将其简化为:
if chess.(y).(x) = 'Q' then
x = x0 || y = y0 || x - x0 = y - y0
但是,如果第一个条件满足,我们只会检查
||
ed 条件,因此我们可以将整个事情重写为:
chess.(y).(x) = 'Q' && (x = x0 || y = y0 || x - x0 = y - y0)
这可以在@octachron发布的答案中看到(但没有详细说明)。
另请注意,您实际上已经接近拥有一个不需要
;;
令牌的格式良好的 OCaml 程序了。最后一个表达式只需是顶级绑定即可。
type chess_board = char array array
type position = int * int
let chess_board_1:chess_board = [|
[|' ';' ';' ';' ';' ';' ';' ';' '|];
[|' ';' ';' ';' ';' ';' ';' ';' '|];
[|' ';' ';' ';' ';' ';' ';' ';' '|];
[|' ';' ';' ';' ';' ';' ';' ';' '|];
[|' ';' ';' ';' ';' ';' ';' ';' '|];
[|' ';' ';' ';' ';' ';' ';' ';' '|];
[|' ';' ';' ';' ';' ';' ';'Q';' '|];
[|' ';' ';' ';' ';' ';' ';' ';' '|];
|]
let queen_targeting (chess:chess_board) pos =
match pos with
|(x0, y0) ->
for y = 0 to Array.length chess -1 do
for x = 0 to Array.length chess.(y) -1 do
if chess.(y).(x) = 'Q'
then
if (
x = x0 || (* Check horizontaly *)
y = y0 || (* Check verticaly *)
x - x0 = y - y0 (* Check diagonaly *)
)
then true
else false
done
done
let () =
queen_targeting chess_board_1 (3, 3) (* Expected true *)