比如go(a, d)。我希望它也打印路线,例如路线 a、路线 b、路线、c 和路线 d
door(a, b).
door(b, c).
door(c, d).
door(b, e).
door(e, f).
door(e, g).
go(FromRoom, ToRoom):-
door(FromRoom,ToRoom).
go(FromRoom, ToRoom) :-
door(FromRoom, NextRoom),
go(NextRoom, ToRoom).
一个好方法是简单地将 go/2 转换为也考虑路由的关系。正如描述列表时经常出现的情况一样,DCG 非常适合:
go(From, To) --> [From, To], { door(From, To) }.
go(From, To) --> [From],
{ door(From, Next) },
go(Next, To).
例子:
?- phrase(go(a, d), Rooms).
Rooms = [a, b, c, d] ;
false.
关于 write/1:这很少需要,因为我们通常可以让顶层负责打印答案。如果需要,format/2 通常比 write/1 更适合格式化输出,例如,而不是:
write('['), write(From), write(':'), write(To), write(']')
你可以写:
format("[~w: ~w]", [From, To])
请尽量不要在谓词中混合 IO 和逻辑。这将使您的代码难以测试、调试和推理,并且会在回溯时产生非常混乱的输出。
在这里,您可以在递归期间将道路保留在列表中。
一个例子是,带有第三个参数:
go(FromRoom, ToRoom, [FromRoom, ToRoom]) :-
door(FromRoom, ToRoom).
go(FromRoom, ToRoom, [FromRoom|Path]) :-
door(FromRoom, NextRoom),
go(NextRoom, ToRoom, Path).
查询正确返回路径:
?- go(a, g, Path).
Path = [a, b, e, g] ;
false.
Path
如有必要,您可以在输出时格式化输出列表。但现在这是一个非常简单的问题:在递归期间格式化列表而不是输出内容。
您需要为此使用写谓词,如下所示
go(FromRoom, ToRoom):-
door(FromRoom,ToRoom),
write('['), write(FromRoom), write(':'), write(ToRoom), write(']').
go(FromRoom, ToRoom) :-
door(FromRoom, NextRoom),
write('['), write(FromRoom), write(':'), write(NextRoom), write(']'),
go(NextRoom, ToRoom).
或者,您想要的格式的路线是
go(FromRoom, ToRoom):-
door(FromRoom,ToRoom),
write(FromRoom), write(' route '), write(ToRoom).
go(FromRoom, ToRoom) :-
door(FromRoom, NextRoom),
write(FromRoom), write(' route '),
go(NextRoom, ToRoom).