% =============================================== % АКИНАТОР - ЗАДАНИЕ 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.