2013-04-10 5 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 - вправо. –

+0

Вы можете использовать 'assert (correct (ChoiceNo)).' Right after 'write ('Right!').'. Затем вызов 'findall (Q, correct (Q), Qs).' В конце викторины даст вам все правильно ответившие вопросы. Тем не менее, это путь «нужный» и «грязный». Если вы предпочитаете избегать вызовов 'assert' (как рекомендовал @CapelliC), я бы предложил вам подумать о другом подходе к вашему алгоритму; больше похож на @CapelliC. –

2

Когда это возможно, следует избегать Assert и втянуть, и, как правило, мы вознаграждены более простых программ, легче понять и отлаживать.

В вашем случае, вы могли бы собрать первоначально список вопросов 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 . 
Смежные вопросы