【问题标题】:Issues with Pathfinding in PrologProlog 中的寻路问题
【发布时间】:2016-11-05 07:15:09
【问题描述】:

所以我在这里有一个 prolog 程序,它接受这样的输入:

mazepath(X,Y,Maze,Path,Score)
mazepath( 1, 1,  [[ o,  e,  j,  p,  o],
     [ o,  j,  o,  o,  o],
     [ o,  j, mt,  j,  o],
     [ o,  o,  e, o, o],
     [ p,  o,  j, mb,  o]], Path, Score).

几乎所有你需要知道的是,j 基本上都是墙。我需要做的是从地图的右上角开始(1,1)我需要找到一个p,一个e,然后找到mb,然后按顺序找到mt。这是我当前的代码:

mazePath(X,Y,Maze,Path,Score) :-
    curVal(X,Y,Maze,V0), %Get the value of the starting point
    findMasterball(X,Y,V0,Maze,Path,PathMB), %Find a path to the Masterball.
    nth1(1,PathMB,Room0), %Use the path generated by findMasterball to get the starting point for findMewtoo
    nth1(1,Room0,Xk),
    nth1(1,Room0,Yk),
    curVal(Xk,Yk,Maze,V1), %Get the value of the Masterball point
    findMewtoo(Xk,Yk,V1,Maze,[[Xk,Yk]],PathM), %Found masterball, starting for Mewtoo
    nth1(1,PathM,Room1), %Now find pika
    nth1(1,Room1,Xs),
    nth1(1,Room1,Ys),
    curVal(Xs,Ys,Maze,V2), %Get the value of the 
    findPika(Xs,Ys,V2,Maze,[[Xs,Ys]]). %Find pika

% findMasterball - recursive predicate that searches for the Masterball
% X,Y - current location
% Val - current value of location
% PathMB - Path traveled so far
% newPath - Path returned
%
%Base Case
findMasterball(_,_,Val,_,PathMB,PathMB) :-
    Val == 'mb',
    length(PathK,L),
    format('~w ~w',['\nPATH TO THE Masterball: ', PathK]),
    format('~w ~w',['\nLENGTH OF PATH: ', L]).

%Recursive Case
findMasterball(X,Y,_,Maze,PathMB,newPath) :-
    nth1(1,Maze,R), %Get width and height of the maze
    length(R,W),
    length(Maze,H),
    nextMove(X,Y,Xn,Yn,Maze,W,H), %Find the next legal move
    curVal(Xn,Yn,Maze,NVal), %Get the value of the next location
    \+ memberchk([Xn,Yn],PathMB), %Make sure we have not traveled to this location before


findMewtoo(_,_,Val,_,PathM,PathM) :-
    Val == 'mt',
    length(PathM,L),
    format('~w ~w',['\n\nPATH TO THE SWORD: ', PathM]),
    format('~w ~w',['\nLENGTH OF PATH: ', L]).

%Recursive Case
findMewtoo(X,Y,_,Maze,PathM,rPathM) :-
    nth1(1,Maze,R), %Get width and height of the maze
    length(R,W),
    length(Maze,H),
    nextMove(X,Y,Xn,Yn,Maze,W,H), %Find the next legal move
    curVal(Xn,Yn,Maze,NVal), %Get the value of the next location
    \+ memberchk([Xn,Yn],PathM), %Make sure we have not traveled to this location before
    findMewtoo(Xn,Yn,NVal,Maze,[[Xn,Yn]|PathM],rPathM). %Recursive call with the next location/value

% findPika - recursive predicate that searches for Pikachoo
% X,Y - current location
% Val - current value of location
% PathPika - Path traveled so far
%
%Base Case
findPika(_,_,Val,_,PikaPath) :-
    Val == 'p',
    length(PikaPath,L),
    format('~w ~w',['\n\nPATH TO THE DUNGEON LORD: ', PikaPath]),
    format('~w ~w',['\nLENGTH OF PATH: ', L]).

%Recursive Case
findPika(X,Y,_,Maze,PikaPath) :-
    nth1(1,Maze,R), %Get width and height of the maze
    length(R,W),
    length(Maze,H),
    nextMove(X,Y,Xn,Yn,Maze,W,H), %Find the next legal move. Doors are walkable.
    curVal(Xn,Yn,Maze,NVal), %Get the value of the next location
    \+ memberchk([Xn,Yn],PikaPath), %Make sure we have not traveled to this location before


% X0, Y0 - Current Location
% X, Y - Variables - Next move will be bound to these variables
% Maze  
% W, H - Width and height of the maze
nextMove(X0,Y0,X,Y,Maze,W,H) :-
    adj(X0,Y0,X,Y),
    inBounds(X,Y,W,H).


% Up
adj(X0,Y0,X0,Y) :-
    Y is Y0+1.

% Down
adj(X0,Y0,X0,Y) :-
    Y is Y0-1.

% Right
adj(X0,Y0,X,Y0) :-
    X is X0+1.

% Left
adj(X0,Y0,X,Y0) :-
    X is X0-1.

% Is X,Y within the bounds of the maze
inBounds(X,Y,W,H) :-
    X >= 1,
    Y >= 1,
    X =< W,
    Y =< H.

% Open space. 
roomOpen(X,Y,Maze) :-
    nth1(Y,Maze,R),
    nth1(X,R,'o').

% This is an egg, pick it up
roomOpen(X,Y,Maze) :-
    nth1(Y,Maze,R),
    nth1(X,R,'e').

% Here's pikachoo
roomOpen(X,Y,Maze) :-
    nth1(Y,Maze,R),
    nth1(X,R,'p').

% Is the masterball there? Pick it up & go catch mewtoo!
roomOpen(X,Y,Maze) :-
    nth1(Y,Maze,R),
    nth1(X,R,'mb').

% Is the mewtoo there?  Catch it if you have the masterball!!
roomOpen(X,Y,Maze) :-
    nth1(Y,Maze,R),
    nth1(X,R,'mt').


%Binds the value of the location of X,Y to Val
curVal(X,Y,Maze,Val) :-
    nth1(Y,Maze,R),
    nth1(X,R,Val).

现在,当我将代码加载到 SWI 中时,我的代码“符合”正常,但是一旦我用上面的测试调用 mazepath,就会发生一些奇怪的事情。当我追踪它时,它正在查看相邻的广场,看看我们是否可以走到其中一个。它从 (1,1) 开始,因此 (1,0) 和 (0,1) 在尝试走到那里时应该会失败。他们确实如此,但是当我的程序查看 (0,1) 时,inBounds 失败,然后整个程序返回 false 而不是继续查找路径。我无法理解为什么它只查看 (1,1) 周围的空间,而不是移动到一个开放的空间并再次寻找大师球。有任何想法吗?

【问题讨论】:

  • “我的代码在加载到 SWI 时可以正常编译” 是吗?当我加载你的代码时,我得到两个operator priority clash errors,一个单例变量和一个nextmove/7 未定义的警告。

标签: prolog path-finding


【解决方案1】:

您的代码存在编译问题:

  • findMasterball/6 的递归案例:在最后一个子句 \+ memberchk([Xn,Yn],PathMB) 后面有一个逗号,而不是句点。
  • findPika/5 的递归案例:在最后一个子句 \+ memberchk([Xn,Yn],PikaPath) 后面有一个逗号,而不是句点。

您的代码也存在语义问题:

  • findMewtoo/6 中,最后一个参数是头部和递归调用中的rPathM:这是一个原子,而不是变量,这几乎肯定不是你想要的。将r 更改为R

  • findMasterball/6 中存在同样的问题,参数 newPath 在头部。

修复所有这些后,您仍然会注意到 SWI-Prolog 告诉您:

Warning: c:/test.pl:1:
        Singleton variables: [Score]
Warning: c:/test.pl:29:
        Singleton variables: [NewPath,NVal]
Warning: c:/test.pl:67:
        Singleton variables: [NVal]
Warning: c:/test.pl:80:
        Singleton variables: [Maze]

这意味着那些行的变量(对应于规则头)在整个规则中只使用一次,这几乎肯定意味着这是一个错误:由于 Prolog 是关于变量之间的关系,它几乎总是不感觉一个变量只会出现一次。这要么意味着我们不关心该变量的值(在这种情况下使用_ 匿名),要么意味着您的程序错误,因为某些变量没有正确使用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多