Prolog101(10)

可以用op/3把任何谓词定义为操作符,每个操作符有不同的优先权值,从1到1200。当某句中有多个操作符时,优先权高的将先被考虑,优先权值越小优先权越高。

Prolog操作符有三种形式,其结合性如下:
中缀(infix):例如3+4
xfx 没有结合性
xfy 从右向左
yfx 从左向右

前缀(prefix):例如-7
fx 没有结合性
fy 从右向左

后缀(postfix):例如8f
xf 没有结合性
yf 从右向左

op/3需要三个参数,分别是:优先权、结合性、操作符名称。

其实Prolog程序的子语句也是使用操作符书写的Prolog数据结构。这里的操作符是”:-“,它是中缀操作符,有两个参数。
:-(Head, Body).

Body也是由操作符书写的数据结构。这里的操作符为”,”,它表示并且的意思,所以Body的形式如下:
,(goal1, ,(goal2,,goal3))

好像看不明白,操作符”,”与分隔符”,”无法区别,所以我们就是用”&”来代替操作符”,”,于是上面的形式就变成了下面这个样子了。
&(goal1, &(goal2, & goal3))

下面的两种形式表达的意思是相同的。
head :- goal1 & goal2 & goal3.
:-(head, &(goal1, &(goal2, & goal3))).

实际上是下面的形式:
head :- goal1 , goal2 , goal3.
:-(head, ,(goal1, ,(goal2, , goal3))).

下面用操作符改写一下roomlist:

%swipl -s operator.pl
%Hansen

%动态函数声明
:-dynamic here/1.
:-dynamic is_in/2.
:-dynamic in_bag/1.
:-dynamic take_thing/2.
:-dynamic put_thing/2.

%定义操作符
:-op(100,fx,is_room).
:-op(101,xfx,is_in).
:-op(101,fx,in_bag).
:-op(101,fx,move).
:-op(101,fx,eat).
:-op(101,f,look).

%房间定义
room(X):- is_room List,member(X,List).
is_room [kitchen,office,hall,diningroom,cellar]. 

%门定义
door(X,Y):- door_list(List),member([X,Y],List).
door_list([[office, hall],[kitchen, office],[hall, diningroom],[kitchen, cellar],[diningroom, kitchen]]).

%规则:有门的两个房间是相通的
connect(X,Y):- door(X,Y).
connect(X,Y):- door(Y,X).

%物品在哪个房间
location(X,Y):- List is_in Y, member(X, List).
[apple, broccoli, crackers] is_in kitchen. 
[desk, computer] is_in office.
[flashlight, envelope] is_in desk.
[stamp, key] is_in envelope.
[] is_in hall.
[] is_in diningroom.
[washingmachine] is_in cellar. 
[nani] is_in washingmachine.

%房间减少物品
take_thing(Thing, Place):- 
retract(List is_in Place),
delete(List,Thing,ThingsLeft),
asserta(ThingsLeft is_in Place). 

%房间增加物品
put_thing(Thing, Place):-  
retract(List is_in Place),
asserta([Thing|List] is_in Place).

%背包有哪些物品
bag(X):-in_bag List, member(X, List).
in_bag [tourch].

%背包增加物品
bag_in(Thing):- 
retract(in_bag List),
asserta(in_bag [Thing|List]).

%背包减少物品
bag_out(Thing):-
retract(in_bag List),
delete(List,Thing,ThingsLeft),
asserta(in_bag ThingsLeft). 

%哪些物品可以吃
edible(X):- 
member(X,[apple,crackers,broccoli]).

%当前位置
here(hall).

%房间之间移动
move(Place):- can_go(Place),retract(here(X)), asserta(here(Place)).
can_go(Place):- here(X), connect(X, Place).
can_go(Place):- write('You can''t go to '),write(Place),write(' from here.'), nl, fail.

%拿起物品
take(X):- can_take(X), here(Place), take_thing(X,Place), bag_in(X), write(X), write(' taken.'), nl.
can_take(Thing):- here(Place), location(Thing, Place).
can_take(Thing):- write('There is no '), write(Thing), write(' here.'), nl, fail.

%放下物品
put(X):- can_put(X), here(Place), bag_out(X), put_thing(X,Place), write(X), write(' put.'), nl.
can_put(Thing):- bag(Thing). 
can_put(Thing):- write('There is no '), write(Thing), write(' in your bag.'), nl, fail. 

%房间物品列表
list_things(Place):- location(X, Place),tab(2),write(X),nl,fail.
list_things(_).

%与Place相连的房间
list_connections(Place):- connect(Place, X),tab(2),write(X),nl,fail.
list_connections(_).

%持有物品列表
list_bag(Thing):- bag(X),tab(2),write(X),nl,fail.
list_bag(_).

%吃东西
eat(Thing):- can_eat(Thing), bag_out(Thing), write(Thing), write(' eaten. Yummy!').
can_eat(Thing):- bag(Thing), edible(Thing).
can_eat(Thing):- not(bag(Thing)), write('There is no '), write(Thing), write(' in your bag.'), nl, fail. 
can_eat(Thing):- bag(Thing), write('You can''t eat the '), write(Thing), write('.'), nl, fail. 

%查看房间情况
look :-
here(Place), write('You are in the '), write(Place), nl,
write('You can see:'),nl,list_things(Place),  
write('You can go to:'), nl, list_connections(Place),
write('You have:'),nl,list_bag(Thing).

%帮助
game :-
write('Look around: look/0'),nl,
write('Move around: move/1'),nl,
write('Take something: take/1'),nl,
write('Eat something: eat/1').

Leave a Reply

Your email address will not be published. Required fields are marked *

*