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).
4

2 回答 2

2

如果可能的话,我们应该避免assertRetract,通常我们会得到更简单的程序,更容易理解和调试的奖励。

在您的情况下,您最初可以收集问题 Qs 的列表

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

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

编辑我只保留 question/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 .
于 2013-04-10T13:43:34.613 回答
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).

我还建议您使用 cut ( !) 或任何其他机制来防止测验完成后回溯。

于 2013-04-10T13:41:10.570 回答