swi prolog简单机器人

时间:2015-03-28 17:15:34

标签: recursion io prolog

我正在prolog中编写一个应该与用户交互的程序。我有一个我喜欢的乐队数据库,我不喜欢,我可以问这些乐队的序言。首先我要说

hello.

到prolog,prolog回答你好,我可以开始问像

这样的问题了
do you like the band motorhead?

和prolog应该回答

yes i like the band because it is rock.

然后我应该能够提出另一个问题。

我最初的想法是获得问题的最后一句话,检查它是否在两个列表之一(likes-list或disliked-list)中,然后递归调用该函数与程序交互

事实上我的代码效果很好,除了一个我无法解决的烦人细节。这是我的问题:

?- hello.
hello!
Ask your question: do you like the band motorhead?
I like the band because it is metal.
Ask your question: I don't know that band.
Ask your question: do you like the band motorhead
I like the band because it is metal.

事实上,当我在问题的末尾添加问号时,prolog回答问题(这里没问题),递归调用函数提问,然后添加“我不知道那个频段”并调用再次提出问题的功能,而不是一次调用,等待我输入另一个问题。

这是我目前与prolog交互的代码

hello :- write('hello!'),nl, ask.
ask :- write('Ask your question: '), 
    getsentence(X), last(Word, X), 
    process(Word).

process(stop) :- !.

process(hello) :- hello, !.

process(X) :- 
  (like-list(LikeList), member(X, LikeList), type(X, Style),
   write('I like the band because it is '), write(Style), write('.'), nl
   ;
   dislike-list(DisLikeList), member(X, DisLikeList),
   write('I don\'t like that band.'), nl
   ;
   write('I don\'t know that band.'), nl),
  ask.

这是我目前用于解析用户输入内容的代码:

getsentence( Wordlist)  :-
  get0( Char),
  getrest( Char, Wordlist).

getrest( 46, [] )  :-  !.               % End of sentence: 46 = ASCII for '.'
getrest( 63, [] )  :-  !.               % 63 = ASCII for '?'
getrest( 10, [] )  :-  !.               % 10 = ASCII for '\n'
getrest( 13, [] )  :-  !.               % 13 = ASCII for 'CR'

getrest( 32, Wordlist)  :-  !,          % 32 = ASCII for blank   
 getsentence( Wordlist).                % Skip the blank 

getrest( Letter, [Word | Wordlist] )  :-
  getletters( Letter, Letters, Nextchar),   % Read letters of current word
  name( Word, Letters),
  getrest( Nextchar, Wordlist).

getletters( 46, [], 46)  :-  !.             % End of word: 46 = full stop 
getletters( 63, [], 63)  :-  !.
getletters( 10, [], 63)  :-  !.
getletters( 13, [], 63)  :-  !.

getletters( 32, [], 32)  :-  !.             % End of word: 32 = blank 

getletters( Let, [Let | Letters], Nextchar)  :-
   get0( Char),
   getletters( Char, Letters, Nextchar).

last(Item, List) :- append(_, [Item], List),!.

1 个答案:

答案 0 :(得分:0)

好的,我设法通过采用不同的方法来解决我的问题。 我希望这对任何人都有用。

hello :-
  write_ln('Robot: Hello!'),
  ask.

/* read_line_to_codes converts what the user typed to ASCII codes, and then
 * with atom_codes, I reconstruct the question from the list of ASCII codes.
 */
ask :-
  write('Me: '),
  read_line_to_codes(user_input, Codes),
  atom_codes(X, Codes),
  process(X), !.

process(stop) :- !.

process(hello) :- hello.

process(X) :-
  ((sub_atom(X, _, _, _, 'do you like the band '),
   like-list(List),
   searchForLikes(X, List, Band, Style),
   write('Robot: '),
   write('I like '),
   write(Band),
   write(' because it is '),
   write(Style), write_ln('.')
  );
   (sub_atom(X, _, _, _, 'do you like the band '),
    dislike-list(List),
   searchForDislikes(X, List, Band, Style),
   write('Robot: '),
   write('I don\'t like '),
   write(Band),
   write(' because it is '),
   write(Style), write_ln('.')
  );
  (X=='what bands do you like?',
   like-list(LikeList),
   write_ln(LikeList)
  );
  (X=='what bands don\'t you like?',
   dislike-list(DislikeList),
   write_ln(DislikeList)
  );
  (sub_atom(X, _, _, _, 'do you like the band '),
   write('Robot: '),
   write_ln('I don\'t know that band.')
  );
  (write('Robot: '),
  write_ln('I don\'t understand the question.'))
  ),
  ask.

/* 
 * term_to_atom transforms for example "ac-dc" to "'ac-dc'" in order to look for that particular atom in the String. 
 * The lookup is done with the function sub_atom (it searches the Band in the string X).
 */
searchForLikes(_, [], _) :- !, fail.
searchForLikes(X, [Head|Tail], Band, Style) :-
  (term_to_atom(Head, Band),
   sub_atom(X, _, _, _, Band),
   type(Head, Style),
   !);
  searchForLikes(X,Tail, Band, Style).

searchForDislikes(_, [], _) :- !, fail.
searchForDislikes(X, [Head|Tail], Band, Style) :-
  (term_to_atom(Head, Band),
   sub_atom(X, _, _, _, Band),
   type(Head, Style),
   !);
  searchForDislikes(X,Tail, Band, Style).

此代码与第一个代码的主要区别在于使用内置函数。