РЕДАКТИРОВАТЬ:
Я заметил, что это решение имеет некоторые проблемы с эффективностью для плат достаточного размера.Это обсуждается здесь .Я обновлю ответ, когда мы придумаем результат.
Будьте осторожны с предикатом assert/1
, так как он постоянно добавляет факт в базу знаний, и он не отменяется при использовании других комбинаций,так что вы не сможете дважды посетить одну и ту же ячейку.
Вместо этого я подошел к ней с дополнительным параметром V
(означает посещенный), в который можно добавить элемент, обработанный вкаждый шаг исследования.Также я сохранил выбранные направления на каждом шаге в списке L
, чтобы распечатать его, когда цель будет найдена.
Оператор or ;
позволяет не продолжать исследовать один и тот же путь, как только цель найдена, ивозвращается, чтобы продолжить пробовать другие комбинации.
Примечания:
Если вы сталкиваетесь с любым вариантом использования, где вы можете использовать assert/1
, будьте осторожны, потому что устарело .
Переменная _
не нужна в функции перемещения, так как вы можете просто добавить 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).
?- getAllPaths.
[r,r,r,r,u,l,l,l,l,u,r,r]
true ;
[r,r,r,r,u,l,l,l,l,u,r,u,l,u,r,r,r,r,d,l,l,d]
true ;
[r,r,r,r,u,l,l,l,l,u,r,u,l,u,r,r,r,r,d,l,d,l]
true ;
[r,r,r,r,u,l,l,l,l,u,r,u,l,u,r,r,r,r,d,d,l,l]
true ;
[r,r,r,r,u,l,l,l,l,u,r,u,l,u,r,r,r,r,d,d,l,u,l,d]
true ;
[r,r,r,r,u,l,l,l,l,u,r,u,l,u,r,r,r,d,l,d]
true ;
[r,r,r,r,u,l,l,l,l,u,r,u,l,u,r,r,r,d,r,d,l,l]
true ;
[r,r,r,r,u,l,l,l,l,u,r,u,l,u,r,r,r,d,d,l]
...