Prolog 比较事实和输出结果
我是Prolog新手,我正在尝试做一个小测验,给用户3个问题和每个问题3个选项。在提出每个问题后,将显示3种可能的答案选择。用户键入该问题的答案,然后显示下一个问题,测验将继续进行,直到所有3个问题都被询问并回答为止 下一步我要做的是将每个用户的答案与该问题的正确答案进行比较,如果用户是对的、错的或跳过了一个问题,则输出。我想我说的是正确的,我需要将数据库知识中的事实与静态事实进行比较。我意识到这不是一个真正的问题,但如果有人能给我建议如何最好地实现我的目标,我将不胜感激。我只是糊涂了。如有需要,将提供更多信息Prolog 比较事实和输出结果,prolog,Prolog,我是Prolog新手,我正在尝试做一个小测验,给用户3个问题和每个问题3个选项。在提出每个问题后,将显示3种可能的答案选择。用户键入该问题的答案,然后显示下一个问题,测验将继续进行,直到所有3个问题都被询问并回答为止 下一步我要做的是将每个用户的答案与该问题的正确答案进行比较,如果用户是对的、错的或跳过了一个问题,则输出。我想我说的是正确的,我需要将数据库知识中的事实与静态事实进行比较。我意识到这不是一个真正的问题,但如果有人能给我建议如何最好地实现我的目标,我将不胜感激。我只是糊涂了。如有需要
question(1,'What is the fifth planet of our Solar System?').
question(2,'In what year was George Best born?').
question(3,'What is the capital of Austraila?').
possibleAns(1,[mars,jupiter,saturn]).
possibleAns(2,[1945,1946,1948]).
possibleAns(3,[sydney,canberra,melbourne]).
rightAns(1,jupiter).
rightAns(2,1946).
rightAns(3,canberra).
skip(s).
%Confused as to how best to achieve the comparing and output
check_answer(AnsNo,userChoice):-
rightAns(AnsNo,Choice),
userAnswer(AnsNo,userChoice)
getChoice(ChoiceNo,ChoiceList):-
write('Choose from'),nl,
write(ChoiceList),nl,
read(Choice),
(member(Choice,ChoiceList);skip(Choice)),
%userAnswer will compare with rightAnswer
assert(userAnswer(ChoiceNo,Choice)).
getChoice(ChoiceNo,ChoiceList):-
writeln('Illegal Choice'),
getChoice(ChoiceNo,ChoiceList).
//check if the question has been asked
//if not, write question
//get users choice and move to next question
get_question(PreviousAsked):-
question(QNum,Text),
\+ member(QNum,PreviousAsked),
write(Text),nl,
possibleAns(QNum,ChoiceList),
getChoice(QNum,ChoiceList),
get_question([QNum|PreviousAsked]).
get_question(_).
start_quiz:-
get_question([]).
由于您已经在数据库中定义了
rightAns/2
,我建议您在getChoice
中比较结果,如下所示:
getChoice(ChoiceNo,ChoiceList):-
write('Choose from'),nl,
write(ChoiceList),nl,
read(Choice),
(member(Choice,ChoiceList);skip(Choice)),
( rightAns(ChoiceNo,Choice)
-> write('Right!'),nl
; write('Wrong.'),nl).
如果您不喜欢比较getChoice/2
中的答案(因为您希望保持谓词的含义尽可能纯粹),您可以创建一个简单的规则:
check_answer(AnsNo,userChoice)
( rightAns(AnsNo,userChoice)
-> write('Right!'),nl
; write('Wrong.'),nl).
我还建议您使用cut(
!
)或任何其他机制来防止测验结束时出现回溯 如果可能,我们应该避免断言和收回,通常我们会得到更简单、更容易理解和调试的程序的奖励
在您的情况下,您可以首先收集问题列表Qs
findall(Q, question(Q,_), Qs)
然后运行一个循环,直到Qs为空。仅当用户选择并以适当方式回答问题时,才删除该问题
编辑我只保留问题/2,可能选项/2,右键/2,并使用此代码
show(Q) :-
question(Q, T),
possibleAns(Q, As),
format('~d: ~s ~w~n', [Q, T, As]).
loop([]).
loop(Qs) :-
maplist(show, Qs),
( (read((Q,Y)),
select(Q, Qs, Rs),
rightAns(Q, Y)
) -> loop(Rs) ; loop(Qs)
).
quiz :-
findall(Q, question(Q,_), Qs),
loop(Qs).
我明白了
谢谢Carles的帮助。这对我有帮助。回答完所有问题后,检查用户的答案,如果答案正确或错误,您将如何检查每个用户的答案和输出。例如,Q1正确,Q2错误,Q3正确。您可以在
write('right!')之后使用assert(correct(ChoiceNo))。
。然后,在测验结束时调用findall(Q,correct(Q),Qs)。
将为您提供所有正确回答的问题。然而,这是一种快速而肮脏的方式。如果您喜欢避免assert
调用(正如@capelical建议的那样),我建议您为您的算法考虑一种不同的方法;更类似于@capelical。
show(Q) :-
question(Q, T),
possibleAns(Q, As),
format('~d: ~s ~w~n', [Q, T, As]).
loop([]).
loop(Qs) :-
maplist(show, Qs),
( (read((Q,Y)),
select(Q, Qs, Rs),
rightAns(Q, Y)
) -> loop(Rs) ; loop(Qs)
).
quiz :-
findall(Q, question(Q,_), Qs),
loop(Qs).
?- quiz.
1: What is the fifth planet of our Solar System? [mars,jupiter,saturn]
2: In what year was George Best born? [1945,1946,1948]
3: What is the capital of Austraila? [sydney,canberra,melbourne]
|: 1,mars.
1: What is the fifth planet of our Solar System? [mars,jupiter,saturn]
2: In what year was George Best born? [1945,1946,1948]
3: What is the capital of Austraila? [sydney,canberra,melbourne]
|: 1,jupiter.
2: In what year was George Best born? [1945,1946,1948]
3: What is the capital of Austraila? [sydney,canberra,melbourne]
|: 2,1946.
3: What is the capital of Austraila? [sydney,canberra,melbourne]
|: 3,canberra.
true .