只贴代码跟样例输出:
move(1,0).%表示船上有一位牧师,没有野人。
move(0,1).
move(0,2).
move(2,0).
move(1,1).
legal((X,Y,_)):- %X为左岸状态,Y为右岸状态。
legal_temp(X), %分别判断两岸的状态是否合法。
legal_temp(Y).
legal_temp((X,Y)):- (X=:=0,Y>=0,!);(Y=:=0,X>=0,!);(X>=Y,X>=0,Y>=0). %牧师人数为0,野人的人数大于0/%野人人数为0,牧师的人数大于0/%牧师人数为0,野人的人数大于0,合法。
update((X,Y,Q),Move,Statu):-(A,B)=X, (C,D)=Y,(E,F)=Move,
if_then_else(
Q=:=0,
(C1 is C+E, D1 is D+F, A1 is A-E, B1 is B-F, Statu=((A1,B1),(C1,D1),1)),
(C1 is C-E, D1 is D-F, A1 is A+E, B1 is B+F, Statu=((A1,B1),(C1,D1),0))
).
valid(Statu,Statu1):- %两种状态互通且可走
move(X,Y),
update(Statu,(X,Y),Statu1),
legal(Statu1).
first_one(A,X):- append([A],_,X). %A等于表X的第一个元素
last_part(A,X):- first_one(B,X),append([B],A,X). %得到A等于表X的除第一个元素的后部分表
if_then_else(P,Q,R):- call(P),!,Q.
if_then_else(P,Q,R):- R.
show(L):-if_then_else((length(L,X),X>0),(first_one(A,L),last_part(B,L),write('['),write(A),write(']'),nl,show(B)),fail).
mcp(X,Y,L):- % L为储存的路由表。
if_then_else(X=Y, (write('================'),nl,show(L),nl) , (valid(X,Z), not(member(Z,L)),mcp(Z,Y,[Z|L])) ).
运行结果:
?- mcp(((0,0),(3,3),1),((3,3),(0,0),0),[((0,0),(3,3),1)]).
================
[(3,3), (0,0),0]
[(2,2), (1,1),1]
[(3,2), (0,1),0]
[(3,0), (0,3),1]
[(3,1), (0,2),0]
[(1,1), (2,2),1]
[(2,2), (1,1),0]
[(0,2), (3,1),1]
[(0,3), (3,0),0]
[(0,1), (3,2),1]
[(0,2), (3,1),0]
[(0,0), (3,3),1]
================
[(3,3), (0,0),0]
[(3,1), (0,2),1]
[(3,2), (0,1),0]
[(3,0), (0,3),1]
[(3,1), (0,2),0]
[(1,1), (2,2),1]
[(2,2), (1,1),0]
[(0,2), (3,1),1]
[(0,3), (3,0),0]
[(0,1), (3,2),1]
[(0,2), (3,1),0]
[(0,0), (3,3),1]
================
[(3,3), (0,0),0]
[(2,2), (1,1),1]
[(3,2), (0,1),0]
[(3,0), (0,3),1]
[(3,1), (0,2),0]
[(1,1), (2,2),1]
[(2,2), (1,1),0]
[(0,2), (3,1),1]
[(0,3), (3,0),0]
[(0,1), (3,2),1]
[(1,1), (2,2),0]
[(0,0), (3,3),1]
================
[(3,3), (0,0),0]
[(3,1), (0,2),1]
[(3,2), (0,1),0]
[(3,0), (0,3),1]
[(3,1), (0,2),0]
[(1,1), (2,2),1]
[(2,2), (1,1),0]
[(0,2), (3,1),1]
[(0,3), (3,0),0]
[(0,1), (3,2),1]
[(1,1), (2,2),0]
[(0,0), (3,3),1]