2013-04-10 27 views
1

我是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([]). 

Updated 
getChoice(ChoiceNo,ChoiceList):- 
    write('Choose from'),nl, 
    write(ChoiceList),nl, 
    read(Choice), 
    (member(Choice,ChoiceList);skip(Choice)), 
    assert(userAnswer(ChoiceNo,Choice)). 
    ( rightAns(ChoiceNo,Choice) 
    -> write('Right!'),nl; 
    write('Wrong,'),nl). 

回答

1

既然你已经在你的数据库中定义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). 

我也建议你使用剪切(!)或任何其他机制,以防止当测验结束回溯。

+0

感谢您的帮助普约尔。这帮助了我。在所有问题得到解答之后,您会检查用户的答案,如果答案是对的或错的,您将如何浏览每个用户的答案并输出结果。例如,Q1正确,Q2错误,Q3正确。 – 2013-04-10 15:31:18

+0

你可以在'write'('Right!')之后使用'assert(correct(ChoiceNo))'。然后,在测验结束时调用'findall(Q,correct(Q),Qs).'会给你所有正确回答的问题。然而,这是一种快速而又脏乱的方式。如果你更喜欢避免'assert'调用(就像@CapelliC推荐的那样),那么我建议你为你的算法考虑一种不同的方法;更类似于@CapelliC。 – 2013-04-10 16:02:19

2

如果可能的话,我们应该避免断言收回,通常我们是通过简单的程序,更容易理解和调试奖励。

在你的情况,你可以收集最初的问题清单Qs的

findall(Q, question(Q,_), Qs) 

,然后运行一个循环,直到Qs成为空。删除问题只有当用户选择它时以适当的方式回答。

编辑我keept唯一的问题/ 2,possibleAns/2,rightAns/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). 

我得到

?- 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 . 
相关问题