如果函数 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]]
我创建了一个函数,我在其中调用了几个函数,但是当其中一个函数 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]]