swipl在递归函数中递增游标

时间:2014-01-26 17:40:22

标签: recursion prolog tail-recursion

我对Prolog非常环保。我有一个7乘7的网格,对于每个单元格,我存储XY和其他两个东西,如:cell(1, 1, 0, 0)

我想遍历网格并重置单元格的值,如果没有给出,所以我创建了这些函数:

given(X, Y):- (cell(X, Y, start, _) ; cell(X, Y, end, _)).
reset_cell(X, Y):- not(given(X, Y)), cell(X, Y, 0, 0).
reset_grid(8, _):- write('finished resetting').
reset_grid(X, 8):- X1 is X + 1, reset_cell(X1, 1), reset_grid(X1, 1).
reset_grid(X, Y):- reset_cell(X, Y), Y1 is Y + 1, reset_grid(X, Y1).

但是这导致无限循环,因为在最后一行显然传递给reset_grid函数的参数保持为值1。我做错了什么?

编辑:我忘了提到我这样称呼函数:?- reset_grid(1, 1).

编辑2:(根据谢尔盖的说明新版本):

reset_grid(X, _):- X > 7, write('finished resetting').
reset_grid(X, Y):- Y > 7, X1 is X + 1, reset_cell(X1, 1), reset_grid(X1, 1).
reset_grid(X, Y):- X < 8, Y < 8, reset_cell(X, Y), Y1 is Y + 1, reset_grid(X, Y1).

1 个答案:

答案 0 :(得分:0)

问题在于,当您拨打电话reset_grid(1, 8)时,您的reset_grid(X, 8)子句会触发,但之后reset_grid(X, Y)也会触发。

要解决此问题,您可以添加剪切'!'到reset_grid(X, 8)子句或将Y < 8添加到reset_grid(X, Y),或两者都做(以获得所谓的'绿色切割')。

调用reset_grid(8, 8)reset_grid(8, _)的类似问题会匹配,但之后reset_grid(X, Y)会匹配。以类似的方式修复。

更新。

尝试将您的重置单元格定义更改为仅记录X和Y.使用以下代码:

reset_cell(X, Y) :- write([X, Y]), nl.
reset_grid(X, _):- X > 7, write('finished resetting').
reset_grid(X, Y):- Y > 7, X1 is X + 1, reset_cell(X1, 1), reset_grid(X1, 1).
reset_grid(X, Y):- X < 8, Y < 8, reset_cell(X, Y), Y1 is Y + 1, reset_grid(X, Y1).

我得到了这个结果:

?- reset_grid(1, 1).
[1,1]
[1,2]
[1,3]
[1,4]
[1,5]
[1,6]
[1,7]
[2,1]
[2,1]
[2,2]
[2,3]
[2,4]
[2,5]
[2,6]
[2,7]
[3,1]
[3,1]
[3,2]
[3,3]
[3,4]
[3,5]
[3,6]
[3,7]
[4,1]
[4,1]
[4,2]
[4,3]
[4,4]
[4,5]
[4,6]
[4,7]
[5,1]
[5,1]
[5,2]
[5,3]
[5,4]
[5,5]
[5,6]
[5,7]
[6,1]
[6,1]
[6,2]
[6,3]
[6,4]
[6,5]
[6,6]
[6,7]
[7,1]
[7,1]
[7,2]
[7,3]
[7,4]
[7,5]
[7,6]
[7,7]
[8,1]
finished resetting
true ;
false.

所以循环工作并终止。也许是上一次电话reset_cell(8, 1)中的问题?否则,它与reset_cell谓词本身或从reset_cell调用的谓词有关。显示其余代码,以便进行测试。