在Prolog中建立一个列表

时间:2011-12-09 01:09:40

标签: prolog

这是我第一次使用Prolog进行编程,我在掌握如何正确使用该语言方面遇到了一些麻烦。我正在构建一个分析谜题的程序,并返回解决谜题的动作(路径)列表。这是一个非常简化的版本:

puzzle(Size,start(StartX,StartY),goal(GoalX,GoalY),Clues,Path) :-
  solve(Size,StartX,StartY,XX,YY,Turns,Clues,GoalX,GoalY,[field(StartX,StartY)],Path).

solve(Size,X,Y,XX,YY,Turns,Clues,GoalX,GoalY,Visited,Path) :-
  X=GoalX, Y=GoalY,!;     
  Turns == 0, neighbor(X,Y,XX,YY), append(link(X,Y,XX,YY),Path,Newpath), solve(Size,XX,YY,XXX,YYY,Turns,Clues,GoalX,GoalY,Visited,Newpath);
  Turns > 1, turn(X,Y,XX,YY), append(link(X,Y,XX,YY), Path, Newpath), solve(Size,XX,YY,XXX,YYY,Turns,Clues,GoalX,GoalY,Visited,Newpath).

我通过递归调用solve函数创建路径,并在每次新调用时以递增方式将某个操作附加到路径,直到达到目标。现在我的问题是最后一个递归调用有我正在寻找的路径,但是如果我问

?- puzzle(3, start(1,1), goal(3,3), [clue(2,1,2),clue(2,2,2)],Path)

它不会返回该路径。举例说明:

   Exit: (13) solve(3, 3, 2, 0, 1, _G1027, _G1028, 1, 0, 1, [clue(2, 2, 2)], 3, 3, [feld(3, 2), feld(3, 1), feld(2, 1), feld(1, 1)], [link(3, 1, 3, 2), link(2, 1, 3, 1), link(1, 1, 2, 1), _G1012]) ? creep

[link(3,1,3,2),link(2,1,3,1),link(1,1,2,1),_ G1012]是我需要的路径。

   Exit: (12) move2(3, 3, 1, 1, 0, _G1027, _G1028, 1, 0, 2, [clue(2, 2, 2)], 3, 3, [feld(3, 1), feld(2, 1), feld(1, 1)], [link(2, 1, 3, 1), link(1, 1, 2, 1), _G1012]) ? creep
   Exit: (11) solve(3, 3, 1, 1, 0, _G1027, _G1028, _G1029, _G1030, 2, [clue(2, 2, 2)], 3, 3, [feld(3, 1), feld(2, 1), feld(1, 1)], [link(2, 1, 3, 1), link(1, 1, 2, 1), _G1012]) ? creep
   Exit: (10) stepfromclue(3, 2, 1, 1, 0, 2, [clue(2, 2, 2)], 3, 3, [feld(2, 1), feld(1, 1)], [link(1, 1, 2, 1), _G1012]) ? creep
   Exit: (9) checkclue(3, 2, 1, 1, 0, [clue(2, 1, 2), clue(2, 2, 2)], 3, 3, [feld(2, 1), feld(1, 1)], [link(1, 1, 2, 1), _G1012]) ? creep
   Exit: (8) solve(3, 1, 1, 1, 0, 2, 1, _G1029, _G1030, 0, [clue(2, 1, 2), clue(2, 2, 2)], 3, 3, [feld(1, 1)], [_G1012]) ? creep
   Exit: (7) puzzle(3, start(1, 1), goal(3, 3), [clue(2, 1, 2), clue(2, 2, 2)], [_G1012]) ? creep
   Exit: (6) puzzle(1, [_G1012]) ? creep

路径= [_G1012]是我得到的路径。我真的无法理解如何在不完全重写程序的情况下“询问”我需要的路径。

1 个答案:

答案 0 :(得分:0)

没有看到完整的代码(包括link/4事实),这有点难以猜测,因为我无法自己跟踪程序。但我认为问题如下:

您尝试做的是通过在路径中附加链接来迭代地构建路径,在变量NewPath中创建新路径:

append(link(X,Y,XX,YY),Path,Newpath),

这里有两个问题。首先,link(X,Y,XX,YY)不是列表,因此append/3将失败。第二个更重要的是,Path是输入变量,NewPath是输出,但是您只将NewPath传递给solve/11的下一个调用,但不是。这样,完整路径永远不会传递回调用者。因此,回到puzzle/5调用的级别,Path变量保持未实例化。

solve的代码应该看起来更像这样:

solve(_,X,Y,_,_,_,_,GoalX,GoalY,_,Path,Path) :-
    X=GoalX, Y=GoalY,!.
solve(Size,X,Y,XX,YY,Turns,Clues,GoalX,GoalY,Visited,PathIn,Path) :-
    Turns == 0, 
    neighbor(X,Y,XX,YY), 
    append(PathIn,[link(X,Y,XX,YY)],PathOut), 
    solve(Size,XX,YY,XXX,YYY,Turns,Clues,GoalX,GoalY,Visited,PathOut,Path).
solve(Size,X,Y,XX,YY,Turns,Clues,GoalX,GoalY,Visited,PathIn,Path) :-
    turn(X,Y,XX,YY), 
    append(PathIn,[link(X,Y,XX,YY)],PathOut), 
    solve(Size,XX,YY,XXX,YYY,Turns,Clues,GoalX,GoalY,Visited,PathOut,Path).

但可以进一步简化。