如果函数 returns false 则如何告诉 prolog 然后跳过它?(15 益智游戏)

How to tell prolog if the function returns false then skip it?(15 puzzle game)

我创建了一个函数,我在其中调用了几个函数,但是当其中一个函数 return 为 false 时,主函数停止并且 return 为 false。那么有没有办法告诉 Prolog 如果函数 returns false 然后跳过它并检查其余部分?

详细说明:我正在尝试将15益智游戏制作为一个项目, 我想制作一个功能,让我可以采取所有可能的下一步行动。

我最终调用了之前控制空白图块的所有函数。

next_move(Board, Moves):-
  swapup(Board,Result),
  swapdown(Board,Result),
  swapright(Board,Result),
  swapleft(Board,Result).

我希望这个函数return所有接下来可能的动作

完整代码如下:

position([Tile|_], Tile, 0).
position([_|Tail], Tile, Index):-
  position(Tail, Tile, Index1),
  Index is Index1+1.

swap(Board,I,J,R) :-
   same_length(Board,R),
   append(BeforeI,[AtI|PastI],Board),
   append(BeforeI,[AtJ|PastI],Bs),
   append(BeforeJ,[AtJ|PastJ],Bs),
   append(BeforeJ,[AtI|PastJ],R),
   length(BeforeI,I),
   length(BeforeJ,J).

swapup(Board,Result):-
    position(Board,0,Index),
    Index \=0,
    Index \=1,
    Index \=2,
    Index \=3,
    Up is Index-4,
    swap(Board,Up,Index,Result).

swapdown(Board,Result):-
    position([],0,Index),
    Index \=12,
    Index \=13,
    Index \=14,
    Index \=15,
    Down is Index+4,
    swap(Board, Down, Index, Result).

swapright(Board,Result):-
    position([],0,Index),
    Index \=3,
    Index \=7,
    Index \=11,
    Index \=15,
    Right is Index+1,
    swap(Board, Right, Index, Result).

swapleft(Board,Result):-
    position([],0,Index),
    Index \=0,
    Index \=4,
    Index \=8,
    Index \=12,
    Left is Index-1,
    swap(Board, Left, Index, Result).

swap(Board,Result) :- swapup(Board,Result).
swap(Board,Result) :- swapdown(Board,Result).
swap(Board,Result) :- swapright(Board,Result).
swap(Board,Result) :- swapleft(Board,Result).

next_move(Board,Moves) :- findall(Result,swap(Board,Result),Moves).

这是一个简单的程序:

a.
b :- fail.
c.

g :- a, b, c.

我可以问g是否成功:

?- g.
false.

没有。

我可以用两种方法解决。

(1)

g :- a, b, c.
g :- a, c.

(2)

g :- a, (b; true), c.

无论如何,g现在成功了:

?- g.
true.

更新

这是您发布的代码:

next_move(Board, Moves) :-
    swapup(Board,Result),
    swapdown(Board,Result),
    swapright(Board,Result),
    swapleft(Board,Result).

在 LHS 上,您有一个变量 Moves,但在 RHS 上没有。 Moves永远无法统一,永远是一个变数。

让我们暂时忽略它,看看 swap 谓词。

如果我假设 Result 是给定 Board 当前状态的有效移动,那么当每个 swap 时,您的代码所说的 next_move(Board, Moves) 都会成功谓词成功,除非您从每个 swap 谓词得到的移动是相同的,否则不会发生这种情况。

一旦 swapup(Board,Result) 成功,它将统一 Result 与“交换”动作。然后你问 swapdown(Board,Result) 是否成功。嗯,Result 不再是一个变量,所以你问你从 swapdown 得到的 Result 是否和你从 [=41= 得到的 Result 一样].我猜不是。

您可能需要这样的东西:

next_move(Board,[U,D,R,L]):-
    swapup(Board,U),
    swapdown(Board,D),
    swapright(Board,R),
    swapleft(Board,L).

但这还不清楚,因为我不知道当你在棋盘上的开 space 已经处于边缘时你会得到什么价值。

您可能更需要这个:

swap(Board,Result) :- swapup(Board,Result).
swap(Board,Result) :- swadown(Board,Result).
swap(Board,Result) :- swapright(Board,Result).
swap(Board,Result) :- swapleft(Board,Result).

next_move(Board,Moves) :- findall(Result,swap(Board,Result),Moves).

但所有这些都是猜测,没有看到您的完整代码。


您的代码现在可以正常工作了。有很多问题。

position/3 就是没用。

这是一个版本:

position(List,Element,Index) :-
    position(List,Element,0,Index).

position([Element|_],Element,Index,Index).
position([_|Tail],Element,Counter,Index) :-
    Next is Counter + 1,
    position(Tail,Element,Next,Index).

您总是以两个索引的相同顺序调用 swap/4。您必须确保它们按升序排列。 swap/4 在任何情况下都不起作用。这是新版本:

swap(BoardIn,I,J,BoardOut) :-
    position(BoardIn,X,I), % find the value `X` at position `I`
    position(BoardIn,Y,J), % find the value `Y` at position `J`
    append(Left,[X|MiddleEnd1],BoardIn), % find the list that is `Left` of `X`
    append(Middle,[Y|End],MiddleEnd1), % find the `Middle` that is left of `Y` and the list `End` that is to the right of `Y`
    append(Middle,[X|End],MiddleEnd2), % put `X` between `Middle` and `End`.
    append(Left,[Y|MiddleEnd2],BoardOut). % put the `Y` between `Left` & `Middle`.

我清理了 swap*/2 谓词。

swapup(BoardIn,BoardOut):-
    position(BoardIn,0,Index),
    Up is Index - 4,
    Up >= 0,
    swap(BoardIn,Up,Index,BoardOut).

swapdown(BoardIn,BoardOut):-
    position(BoardIn,0,Index),
    Down is Index + 4,
    Down =< 15,
    swap(BoardIn,Index,Down,BoardOut).

swapright(BoardIn,BoardOut):-
    position(BoardIn,0,Index),
    Index mod 4 =\= 3,
    Right is Index + 1,
    swap(BoardIn,Index,Right,BoardOut).

swapleft(BoardIn,BoardOut):-
    position(BoardIn,0,Index),
    Index mod 4 =\= 0,
    Left is Index - 1,
    swap(BoardIn,Left,Index,BoardOut).

swap(BoardIn,BoardOut) :- swapup(BoardIn,BoardOut).
swap(BoardIn,BoardOut) :- swapdown(BoardIn,BoardOut).
swap(BoardIn,BoardOut) :- swapright(BoardIn,BoardOut).
swap(BoardIn,BoardOut) :- swapleft(BoardIn,BoardOut).

最后,这里是 next_move/2 谓词:

next_move(BoardIn,Moves) :-
    length(BoardIn,16),
    position(BoardIn,0,_),
    findall(BoardOut,swap(BoardIn,BoardOut),Moves).

现在我可以调用这个查询:

?- next_move([1,0,2,3,4,5,6,7,8,9,10,11,12,13,14,15],Result),write(Result).

我得到这个结果:

[[1,5,2,3,4,0,6,7,8,9,10,11,12,13,14,15],[1,2,0,3,4,5,6,7,8,9,10,11,12,13,14,15],[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]]