我遇到了Prolog的问题,因为cut没有做(我相信)它应该做的事情:
% line-column handlers
checkVallEle(_, _, 6, _):- write('FAIL'), !, fail.
checkVallEle(TABULEIRO, VALUE, LINE, COLUMN):- COLUMN>5, NL is LINE+1, checkVallEle(TABULEIRO, VALUE, NL, 0).
% if this fails, it goes to the next
checkVallEle(TABULEIRO, VALUE, LINE, COLUMN):-
(checkHorizontal(TABULEIRO, VALUE, LINE, COLUMN, 0), write('HORIZONTAL ');
checkVertical(TABULEIRO, VALUE, LINE, COLUMN, 0), write('VERTICAL');
checkDiagonalRight(TABULEIRO, VALUE, LINE, COLUMN, 0), write('DIAGONALRIGHT');
checkDiagonalLeft(TABULEIRO, VALUE, LINE, COLUMN, 0), write('DIAGONALLEFT')),
write('WIN').
% goes to the next if above fails
checkVallEle(TABULEIRO, VALUE, LINE, COLUMN):-
NC is COLUMN+1,
checkVallEle(TABULEIRO, VALUE, LINE, NC).
我希望做的是,如果代码到达第一个语句,也就是说,如果该行是6,那么它就会失败(因为它超出了范围),而没有检查更多的可能性。但是,当它到达第一个语句时,它会继续执行以下语句并忽略剪切符号,我不明白为什么。我只是希望语句在到达第一行时失败。
我也有经验......
run(6):-write('done'), !, fail.
run(X):-X1 is X+1, run(X1).
这就是我从追踪中获得的:
| ?- run(0).
1 1 Call: run(0) ?
2 2 Call: _1079 is 0+1 ?
2 2 Exit: 1 is 0+1 ?
3 2 Call: run(1) ?
4 3 Call: _3009 is 1+1 ?
4 3 Exit: 2 is 1+1 ?
5 3 Call: run(2) ?
6 4 Call: _4939 is 2+1 ?
6 4 Exit: 3 is 2+1 ?
7 4 Call: run(3) ?
8 5 Call: _6869 is 3+1 ?
8 5 Exit: 4 is 3+1 ?
9 5 Call: run(4) ?
10 6 Call: _8799 is 4+1 ?
10 6 Exit: 5 is 4+1 ?
11 6 Call: run(5) ?
12 7 Call: _10729 is 5+1 ?
12 7 Exit: 6 is 5+1 ?
13 7 Call: run(6) ?
14 8 Call: write(done) ?
done
14 8 Exit: write(done) ?
13 7 Fail: run(6) ?
11 6 Fail: run(5) ?
9 5 Fail: run(4) ?
7 4 Fail: run(3) ?
5 3 Fail: run(2) ?
3 2 Fail: run(1) ?
1 1 Fail: run(0) ?
no
写完后失败的是什么?它仍然回到以前的答案吗?这种行为是我的第一个代码中切割失败的原因吗?请赐教。
答案 0 :(得分:0)
考虑最后一步,您正在评估run(5):-run(6).
。 run(6)
失败,这意味着run(5)
失败,这当然意味着run(4)
失败,依此类推。
至于你原来的问题,它并没有忽略削减。剪切不会完全停止回溯,它只会停止回溯checkVallEle(_,_,6,_)
的解决方案 - 一旦失败,它将开始回溯以获得LINE=5
的更多解决方案。
真正的问题是你的其他规则都受到了限制。一旦用COLUMN=6
尝试了第二个案例,它将使用COLUMN=6
尝试第三个案例 - 没有任何东西可以阻止它。你可以通过向它投掷更多的削减来解决这个问题,但这不是一个非常好的方法。
更好的方法是明确所有约束。只要在每个其他规则的开头都说checkVallEle(_,_,6,_)
,就不需要LINE<6
。如果你在每个规则中都说COLUMN<6
(当然除了第二个规则),它应该通过意外的回溯来解决你的问题。