You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

350 lines
13 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

% ===============================================
% АКИНАТОР - ЗАДАНИЕ 4
% Модификация акинатора с добавлением объектов
% ===============================================
% Объекты без дополнительных вопросов (определяются существующими)
object(собака).
object(кошка).
object(рыбка).
object(попугай).
% Новые объекты, требующие дополнительных вопросов
object(хомяк).
object(черепаха).
object(игуана).
object(канарейка).
% ===============================================
% БАЗОВЫЕ ВОПРОСЫ
% ===============================================
% Основные характеристики
question(has_fur, 'Есть ли у животного шерсть?').
question(can_fly, 'Умеет ли животное летать?').
question(lives_in_water, 'Живет ли животное в воде?').
question(makes_sound, 'Издает ли животное звуки?').
% Дополнительные вопросы для новых объектов
question(is_small, 'Это маленькое животное (помещается в ладонь)?').
question(has_shell, 'Есть ли у животного панцирь?').
question(is_reptile, 'Это рептилия?').
question(can_sing, 'Умеет ли животное петь?').
% ===============================================
% ПРАВИЛА ДЛЯ ОПРЕДЕЛЕНИЯ ОБЪЕКТОВ
% ===============================================
% Объекты без дополнительных вопросов
knows(собака) :-
answer(has_fur, yes),
answer(can_fly, no),
answer(lives_in_water, no),
answer(makes_sound, yes).
knows(кошка) :-
answer(has_fur, yes),
answer(can_fly, no),
answer(lives_in_water, no),
answer(makes_sound, yes),
\+ answer(is_small, yes). % Не маленькая
knows(рыбка) :-
answer(has_fur, no),
answer(can_fly, no),
answer(lives_in_water, yes).
knows(попугай) :-
answer(has_fur, no),
answer(can_fly, yes),
answer(makes_sound, yes),
\+ answer(can_sing, yes). % Не поет специально
% Новые объекты с дополнительными вопросами
knows(хомяк) :-
answer(has_fur, yes),
answer(can_fly, no),
answer(lives_in_water, no),
answer(is_small, yes),
answer(makes_sound, no).
knows(черепаха) :-
answer(has_fur, no),
answer(can_fly, no),
answer(has_shell, yes),
answer(is_reptile, yes).
knows(игуана) :-
answer(has_fur, no),
answer(can_fly, no),
answer(lives_in_water, no),
answer(is_reptile, yes),
answer(has_shell, no).
knows(канарейка) :-
answer(has_fur, no),
answer(can_fly, yes),
answer(makes_sound, yes),
answer(can_sing, yes),
answer(is_small, yes).
% ===============================================
% СИСТЕМА АКИНАТОРА
% ===============================================
% Запуск акинатора
start_akinator :-
write('=== АКИНАТОР ЗАДАНИЕ 4 ==='), nl,
write('Загадайте животное из списка:'), nl,
show_objects,
nl,
write('Отвечайте на вопросы yes/no'), nl,
write('Для выхода введите quit'), nl,
nl,
retractall(answer(_, _)),
ask_questions.
% Основной цикл вопросов
ask_questions :-
% Попробуем определить объект с текущими ответами
( find_object(Object) ->
write('Вы загадали: '), write(Object), write('!'), nl,
write('Правильно? (yes/no): '),
read(Response),
handle_guess_response(Response, Object)
; % Если не можем определить, задаем следующий вопрос
find_next_question(Question),
ask_question(Question),
ask_questions
).
% Найти объект, который соответствует текущим ответам
find_object(Object) :-
object(Object),
knows(Object),
!.
% Найти следующий вопрос для задавания
find_next_question(Question) :-
question(Question, _),
\+ answer(Question, _),
!.
% Задать вопрос пользователю
ask_question(Question) :-
question(Question, Text),
write(Text), write(' (yes/no/quit): '),
read(Response),
handle_response(Question, Response).
% Обработка ответа на вопрос
handle_response(_, quit) :-
write('До свидания!'), nl, !.
handle_response(Question, yes) :-
assert(answer(Question, yes)).
handle_response(Question, no) :-
assert(answer(Question, no)).
handle_response(Question, _) :-
write('Пожалуйста, ответьте yes, no или quit'), nl,
ask_question(Question).
% Обработка ответа на догадку
handle_guess_response(yes, Object) :-
write('Отлично! Я угадал '), write(Object), write('!'), nl,
write('Хотите играть еще? (yes/no): '),
read(Again),
( Again = yes ->
start_akinator
; write('Спасибо за игру!'), nl
).
handle_guess_response(no, Object) :-
write('Я ошибся с '), write(Object), write('.'), nl,
write('Какое животное вы загадали? '),
read(CorrectObject),
write('Спасибо! В следующий раз я буду умнее.'), nl,
learn_new_object(CorrectObject),
write('Хотите играть еще? (yes/no): '),
read(Again),
( Again = yes ->
start_akinator
; write('Спасибо за игру!'), nl
).
handle_guess_response(quit, _) :-
write('До свидания!'), nl.
handle_guess_response(_, Object) :-
write('Пожалуйста, ответьте yes, no или quit'), nl,
write('Я думаю это '), write(Object), write('. Правильно? '),
read(Response),
handle_guess_response(Response, Object).
% Обучение новому объекту (упрощенная версия)
learn_new_object(Object) :-
write('Добавляю '), write(Object), write(' в базу знаний...'), nl.
% ===============================================
% ДЕМОНСТРАЦИОННЫЕ ФУНКЦИИ
% ===============================================
% Показать все объекты
show_objects :-
write('Доступные объекты:'), nl,
forall(object(Obj), (write(' - '), write(Obj), nl)).
% Показать все вопросы
show_questions :-
write('Доступные вопросы:'), nl,
forall(question(Q, Text),
(write(' '), write(Q), write(': '), write(Text), nl)).
% Показать правила для объекта
show_rules(Object) :-
write('Правила для '), write(Object), write(':'), nl,
( knows(Object) ->
write(' Объект определяется существующими правилами'), nl
; write(' Правила не найдены'), nl
).
% Демонстрация объектов без дополнительных вопросов
demo_simple_objects :-
write('=== ОБЪЕКТЫ БЕЗ ДОПОЛНИТЕЛЬНЫХ ВОПРОСОВ ==='), nl,
SimpleObjects = [собака, кошка, рыбка, попугай],
forall(member(Obj, SimpleObjects),
(write('- '), write(Obj), nl)).
% Демонстрация объектов с дополнительными вопросами
demo_complex_objects :-
write('=== ОБЪЕКТЫ С ДОПОЛНИТЕЛЬНЫМИ ВОПРОСАМИ ==='), nl,
ComplexObjects = [хомяк, черепаха, игуана, канарейка],
forall(member(Obj, ComplexObjects),
(write('- '), write(Obj), write(' (требует: '),
show_additional_questions(Obj), write(')'), nl)).
% Показать дополнительные вопросы для объекта
show_additional_questions(хомяк) :- write('is_small').
show_additional_questions(черепаха) :- write('has_shell, is_reptile').
show_additional_questions(игуана) :- write('is_reptile').
show_additional_questions(канарейка) :- write('can_sing, is_small').
show_additional_questions(_) :- write('нет').
% Тестирование определения объектов
test_object_recognition :-
write('=== ТЕСТИРОВАНИЕ РАСПОЗНАВАНИЯ ОБЪЕКТОВ ==='), nl,
% Тест 1: Собака (без дополнительных вопросов)
write('Тест 1: Собака'), nl,
retractall(answer(_, _)),
assert(answer(has_fur, yes)),
assert(answer(can_fly, no)),
assert(answer(lives_in_water, no)),
assert(answer(makes_sound, yes)),
( knows(собака) ->
write(' ✓ Собака определена правильно'), nl
; write(' ✗ Ошибка определения собаки'), nl
),
% Тест 2: Хомяк (с дополнительными вопросами)
write('Тест 2: Хомяк'), nl,
retractall(answer(_, _)),
assert(answer(has_fur, yes)),
assert(answer(can_fly, no)),
assert(answer(lives_in_water, no)),
assert(answer(is_small, yes)),
assert(answer(makes_sound, no)),
( knows(хомяк) ->
write(' ✓ Хомяк определен правильно'), nl
; write(' ✗ Ошибка определения хомяка'), nl
),
% Тест 3: Черепаха (с дополнительными вопросами)
write('Тест 3: Черепаха'), nl,
retractall(answer(_, _)),
assert(answer(has_fur, no)),
assert(answer(can_fly, no)),
assert(answer(has_shell, yes)),
assert(answer(is_reptile, yes)),
( knows(черепаха) ->
write(' ✓ Черепаха определена правильно'), nl
; write(' ✗ Ошибка определения черепахи'), nl
),
retractall(answer(_, _)),
nl.
% Интерактивная демонстрация
demo :-
write('=== ДЕМОНСТРАЦИЯ АКИНАТОРА ЗАДАНИЕ 4 ==='), nl, nl,
write('1. ПОКАЗАТЬ ВСЕ ОБЪЕКТЫ'), nl,
write('========================'), nl,
show_objects,
nl,
write('2. ПОКАЗАТЬ ВСЕ ВОПРОСЫ'), nl,
write('========================'), nl,
show_questions,
nl,
write('3. ОБЪЕКТЫ БЕЗ ДОПОЛНИТЕЛЬНЫХ ВОПРОСОВ'), nl,
write('======================================'), nl,
demo_simple_objects,
nl,
write('4. ОБЪЕКТЫ С ДОПОЛНИТЕЛЬНЫМИ ВОПРОСАМИ'), nl,
write('====================================='), nl,
demo_complex_objects,
nl,
write('5. ТЕСТИРОВАНИЕ РАСПОЗНАВАНИЯ'), nl,
write('============================'), nl,
test_object_recognition,
write('6. ЗАПУСК ИНТЕРАКТИВНОГО АКИНАТОРА'), nl,
write('=================================='), nl,
write('Для запуска интерактивной игры используйте: ?- start_akinator.'), nl,
nl,
write('=== ДЕМОНСТРАЦИЯ ЗАВЕРШЕНА ==='), nl.
% ===============================================
% ВСПОМОГАТЕЛЬНЫЕ ПРЕДИКАТЫ
% ===============================================
% Подсчет количества объектов
count_objects(Count) :-
findall(Obj, object(Obj), Objects),
length(Objects, Count).
% Подсчет количества вопросов
count_questions(Count) :-
findall(Q, question(Q, _), Questions),
length(Questions, Count).
% Проверка, является ли объект простым (без дополнительных вопросов)
is_simple_object(Object) :-
member(Object, [собака, кошка, рыбка, попугай]).
% Проверка, является ли объект сложным (с дополнительными вопросами)
is_complex_object(Object) :-
member(Object, [хомяк, черепаха, игуана, канарейка]).
% Получить статистику
akinator_stats :-
count_objects(ObjCount),
count_questions(QCount),
findall(O, is_simple_object(O), Simple),
findall(C, is_complex_object(C), Complex),
length(Simple, SimpleCount),
length(Complex, ComplexCount),
write('=== СТАТИСТИКА АКИНАТОРА ==='), nl,
write('Всего объектов: '), write(ObjCount), nl,
write('Всего вопросов: '), write(QCount), nl,
write('Простых объектов: '), write(SimpleCount), nl,
write('Сложных объектов: '), write(ComplexCount), nl,
nl.