can_go(Place) :- here(X), connect(X, Place).
can_go(Place) :- ('You cannnot get there from here'), nl,
fail.
can_go(location(treasure,room)) :- location(key,in_hand).
can_go(location(treasure,room)) :- write('cannot enter here without keys'), nl,
fail.
答案 0 :(得分:0)
这里涉及两个不同的概念:您是否可以从一个地方到另一个地方,以及您是否允许从一个地方到另一个地方。通常,您应该针对不同的概念使用不同的谓词。物理可达性部分由您的connect/2
谓词建模,但让它更明确:
reachable(Place) :-
here(X),
connect(X, Place).
然后,让我们将定义的其他部分重命名为allowed_to_go/1
:
allowed_to_go(location(treasure,room)) :-
location(key,in_hand).
allowed_to_go(location(treasure,room)) :-
write('cannot enter here without keys'), nl,
fail.
现在,你可以去某个地方,如果那个地方可以到达,和你可以去那里。连词(“和”)只是逗号(,
):
can_go(Place) :-
reachable(Place),
allowed_to_go(Place).
can_go(Place) :-
write('You cannnot get there from here'), nl,
fail.
剩下的问题是,如果某个地方可以到达但你不允许去那里,你将打印两条错误信息,其中一条是无关紧要的。有几种方法可以解决这个问题。有些人可能会建议添加一个剪切(!
),但如果有更简单,更清晰的选择,你应该避免这种情况。在这种特殊情况下,否定可能是最简单的可能性。如果在can_go/1
的第二个子句中添加一个保护,则不会出现虚假错误:
can_go(Place) :-
\+ reachable(Place),
write('You cannnot get there from here'), nl,
fail.
另一种方法是使用if-then-else运算符(->
)。 (注意:我没有测试任何一个。)