2015-06-20 100 views
1

我堅持了這個問題...如何打印所有的事實?

isAt(keys, room3). 
isAt(book, room3). 
isAt(keys, room6). 
isAt(keys, room4). 

目前,ROOM3有按鍵和書籍。 我想打印鍵和書。 我試過這段代碼,顯然只打印一個。 (只是鍵)

look :- isIn(Location), 
    write('You are in '), 
    write(Location), 
    nl, 
    items_inroom(Location), 
    nl. 


items_inroom(Location) :- 
    isIn(Location), 
    isAt(Item, Location), 
    write('Available Item(s):'), 
    write(Item), 
    nl. 

items_inroom(_) :- 
    write('Available Item(s): None'), 
    nl. 

items_inroom是試圖打印所有這些事實的代碼。 我該如何解決這個問題? 任何幫助將是偉大的!謝謝。

回答

0

查找所有項目並顯示它們。

items_inroom(Location) :- 
    write('Available Item(s):'), 
    findall(Item, isAt(Item, Location), Items), 
    show_items(Items). 

show_items([]) :- 
    write('None'), !. 

show_items(Items) :- 
    write(Items). 

其實你可以用你想要的任何方式實現​​。

+2

理想情況下,你會想用'bagof/3'或'SETOF/3',而不是'findall'(因爲他們失敗,如果沒有解決,不踐踏的選擇點是'findall'的方式做)。 – 2015-06-22 11:20:28

+0

@Boris你是對的。我的主要目的是清楚地分離*數據處理*和*用戶界面*。 – dlask

+1

謝謝你的幫助!有用。 @dlask – drunktiger

2

由理查德·奧基夫,有點簡化第11章"The Craft of Prolog" /重構,以節省擊鍵:

 
print_item_report(Location) :- 
    ( setof(Item, isAt(Item, Location), Items) 
    -> format("Items available in ~w:~n", [Location]), 
     forall(member(I, Items), 
       format("~w~n", [I])) 
     % print_item_report_footer 
    ; format("No items in ~w~n", [Location]) 
    ). 

% etc 

如果您還沒有format不管是什麼原因呢,你仍然可以使用write。如果你沒有做forall,那麼這個:

forall(Condition, Action) 

被定義爲

\+ (Condition, \+ Action) 

,所以你可以使用來代替。詳情請參閱the SWI-Prolog forall/2 documentation

+0

謝謝! @Boris – drunktiger

0

items_inroom/1謂詞總是會在所有事實isAt/2上打印第一個出現的Item。您需要遍歷所有的事實isAt/2,使用metapredicate setof/3bagog/3findall/3,我會建議更換setof/3像@Boris那樣,或建立自己的bucle(也許不是最好的辦法,但它是一個選項):

show_items(Location):- isAt(Item, Location), % Condition 
        write(Item), nl,   % Process result 
        fail.      % force backtracking to evaluate condition and find a new result 
show_items(_).         % return true when all options have been evaluated 
+0

謝謝! @Yasel – drunktiger