如何在Prolog中回退NxN板?

时间:2019-02-14 12:17:56

标签: prolog

我目前必须在SWI Prolog中进行某种Wumpus World的实现,并在大小为 NxN 的板上给出所有可能的路径,我已经完成了一些prolog教程,但我不知道该如何做。解决Prolog中的这一特殊任务。我正在设法为我的经纪人提供所有可能的途径,让他们获得金子,仅此而已。它必须从初始位置(X0,Y0)开始。

我附上了到目前为止我已经设法编写的代码。我试图做一个简单的DFS来完成这类工作,但是我在使用变量“ parsing”来完成代码方面很挣扎。

:- dynamic getAllPathsRec/2, agent/2, visited/2, visited/2.

gold(5,5).

worldSize(10).

agent(1,1).

getAllPaths :-
    getAllPathsRec(1,1).

getAllPathsRec(X,Y) :-
    format(X), format(Y), format('~n'),
    gold(X1,Y1),
    \+visited(X,Y),
    assert(visited(X,Y)),
    (X = X1, Y = Y1) -> print('Found GOLD');
    move(_,X,Y).

move(right, X, Y) :-
    X1 is X + 1,
    X1 > 0 , X1 < 11,
    getAllPathsRec(X1,Y).
move(left, X, Y) :-
    X1 is X - 1,
    X1 > 0 , X1 < 11,
    getAllPathsRec(X1,Y).
move(up, X, Y) :-
    Y1 is Y + 1,
    Y1 > 0 , Y1 < 11,
    getAllPathsRec(X,Y1).
move(down, X, Y) :-
    Y1 is Y - 1,
    Y1 > 0 , Y1 < 11,
    getAllPathsRec(X,Y1).

我希望以任何可能的方式找到黄金,理想情况下会打印算法采用的每条路径。预先谢谢你。

1 个答案:

答案 0 :(得分:2)

编辑:

我已经注意到,对于足够大的电路板,该解决方案存在一些效率问题。 here正在讨论中。当我们得出结果时,我将更新答案。


请谨慎使用#include <optional> #include <boost/container/flat_set.hpp> std::optional<boost::container::flat_set<int> > objects; template<class T> auto assure_contents(std::optional<T>& opt) -> T& { if (opt.has_value()) return *opt; else return opt.emplace(); } void f(int _v) { assure_contents(objects).insert(_v); } 谓词,因为它将永久性地将事实添加到知识库中,并且在尝试其他组合时不会撤消,因此您将无法两次访问同一单元格。

相反,我使用一个额外的参数assert/1(代表已访问)来处理它,您可以在其中附加在每个探索步骤中处理过的元素。另外,我将每一步中选择的方向存储在列表V中,以便在找到目标时将其打印出来。

或运算符L允许在找到目标后不再继续探索同一条路径,然后返回以继续尝试其他组合。


注释:

  • 如果遇到任何可以使用;的用例,请多加注意,因为它是deprecated

  • assert/1变量在move函数中不是必需的,因为您可以简单地添加4个不同的“实现”并只需追加四个方向即可。

  • 作为建议,请使用事实或知识(也称为“世界尺寸”,“目标位置”和“玩家位置”)作为变量,并且不要对其进行硬编码。调试和尝试不同的参数会更容易。


这里有工作代码和一些输出示例:

_
:- dynamic 
    getAllPathsRec/2,
    agent/2,
    visited/2.

gold(3, 3).
worldSize(5).
agent(1, 1).

getAllPaths :-
    agent(X, Y),
    getAllPathsRec(X, Y, [], []).

getAllPathsRec(X, Y, V, L) :-
    hashPos(X, Y, H), \+member(H, V), append(V, [H], VP),
    ((gold(X, Y), print(L)) ; move(X, Y, VP, L)).

% Hash H from h(X, Y)
hashPos(X, Y, H) :- H is (X*100 + Y).

% Left
move(X, Y, V, L) :-
    XP is X - 1, XP > 0,
    append(L, [l], LP),
    getAllPathsRec(XP, Y, V, LP).

% Right
move(X, Y, V, L) :-
    XP is X + 1, worldSize(MS), XP =< MS,
    append(L, [r], LP),
    getAllPathsRec(XP, Y, V, LP).

% Up
move(X, Y, V, L) :-
    YP is Y + 1, worldSize(MS), YP =< MS,
    append(L, [u], LP),
    getAllPathsRec(X, YP, V, LP).

% Down
move(X, Y, V, L) :-
    YP is Y - 1, YP > 0,
    append(L, [d], LP),
    getAllPathsRec(X, YP, V, LP).