БЛОК-СХЕМА РАБОТЫ ИНТЕРПРЕТАТОРА
Анализатор команд – это подпрограмма, на входе которой находится введенная игроком строка, а на выходе массив, состоящий из значений – Действие, Основной, Дополнительный и Вспомогательный предметы, а также количество по каждому из них. Или ошибка и сообщение с причиной.
Процедура ПоискДействия(Строка)
Входящие данные: строка, которая должна содержать только один глагол, а также все относящиеся к нему имена существительные, прилагательные, числительные, предлоги и наречия.
Описание: ищет в строке действие и предметы и составляет из них массив, каждая строка которого будет содержать некоторое действие к выполнению.
Алгоритм:
v Запускаем процедуру ПроверкаСлов(Строка). Если строка с ошибками, то дальше не идём.
v Последовательно каждое слово в строке ищем в списке наречий;
Ø Если нашли, то удаляем слово из строки и ищем дальше (пока опустим обработку наречий);
v Последовательно каждое слово в строке ищем в списке глаголов;
Ø Если нашли, то запоминаем глагол, удаляем слово из строки и заканчиваем поиск глагола;
Ø Если нет, то ошибка. Такая строка не должна попадать в эту процедуру.
v Отправляем полученную строку без глагола в функцию РазделениеПредметов(Строка,Глагол);
v Отправляем полученный из функции массив в функцию РасстановкаПредметов(Массив, Глагол);
v Получили другой массив. Он выглядит следующим образом:
Основной предмет |
Кол-во |
Предлог |
Дополнительный предмет |
Кол-во |
Предлог |
Вспомогательный предмет |
Кол-во |
v Делаем цикл по строкам:
Ø Если глагол непереходный, то есть основной предмет указывать не нужно, а он указан, то ошибка. И наоборот – тоже ошибка.
Ø Ищем среди конструкций глагола такую, в которой участвует указанный набор предметов и указанные предлоги. Если не найдена – ошибка.
Ø Если найдена, то ищем действие, которое описывает данная конструкция. Если такое действие не существует – ошибка.
Ø Добавляем действие, найденные предметы и их количество в результирующий массив данной функции.
v Дело сделано – получили массив с действиями, предметами и их количеством.
Процедура ПроверкаСлов(Строка)
Входящие данные: строка текста, введённая игроком.
Описание: проверяет наличие каждого из слов строки в своём словарном запасе.
И выдаёт ошибку, если что не так. Если есть желание, можно попытаться автоматически исправить ошибки. Также должна проверять указание нескольких предлогов или разделителей подряд и указание разделителя сразу после предлога. Эта процедура должна вычленить очевидные ошибки в строке.
Процедура РазделениеПредметов(Строка, Глагол)
Входящие данные: строка, которая содержит команду без глагола, то есть, по сути, информацию о предметах.
Результат: массив вида:
Предлог |
Количество |
Падеж |
Предмет в игровой базе |
Флаг наличия разделителя |
Описание: эта процедура делит входящую строку на части, относящиеся к каждому из предметов. Каждая такая часть анализируется и порождает одну строчку результирующего массива.
Алгоритм:
v Ищем первое имя существительное в строке. Если не найдено, то ошибка;
Ø Правее найденного имени ищем первый предлог, имя существительное или разделитель «и» или «,»;
§ Если там предлог или разделитель, то всё, что до него, относится к текущему имени существительному;
§ Если там другое существительное, то все слова между ними будем относить к тому, что находится правее в строке (В дальнейшем можно усложнить алгоритм, анализируя наличие числительных и падеж прилагательных между существительными);
Ø В найденной подстроке разделителей быть не должно, но не факт, нужно проверить. Пока можно их попросту удалять.
Ø В подстроке ищем предлог. Он там должен быть один (иначе – ошибка). Найденный предлог вырезаем из строки и добавляем в массив.
Ø Подстроку без предлога отправляем в функцию ПоискПредмета(Строка,Глагол,Предлог), а возвращённые предмет и количество добавляем в результирующий массив;
v Возвращаем результирующий массив. Он выглядит следующим образом:
Предлог |
Количество |
Падеж |
Предмет в игровой базе |
Флаг наличия разделителя |
Функция ПоискПредмета(Строка,Глагол,Предлог)
Входящие данные: строка, которая должна содержать только имена существительные и прилагательные, а также числительные. Последние должны находиться в начале строки, дальнейший порядок не важен. Глагол и предлог идут отдельно.
Результат: предмет в игровой базе, количество и падеж, в котором он описан в строке. Или ошибка.
Алгоритм:
v Ищем первое в строке слово среди числительных;
Ø Если нашли, то Количество=Количество + найденная сумма, удаляем первое слово из строки и ищем дальше;
Ø Если нет, то дальше числительных уже быть не должно (желательно этот факт проверить и вывести ошибку, если что не так). Если числительных не было вообще, то Количество=1;
v Последовательно каждое слово в строке ищем среди имен прилагательных;
Ø Если нашли, то добавляем в массив найденное имя, удаляем слово из строки и ищем дальше;
v Ищем первое в строке слово среди имен существительных;
Ø Если нашли, то добавляем в массив найденное имя, удаляем первое слово из строки и ищем дальше;
Ø Если нет, то ошибка - такого слова нет в базе;
v Строка должна быть пуста. Имеем: количество, набор имён существительных и набор имен прилагательных. Узнаём падеж слов строке со следующими правилами:
Ø Если по написанию имени существительного можно точно определить падеж, то берем его. Падеж прилагательных в этом случае роли не играет
Ø Если же определить нельзя (например, «пальто»), тогда определяем падеж по совокупности всех имен прилагательных и существительного. Если задача имеет решением один единственный падеж – берем его.
Ø Если в функцию передали предлог, тогда среди конструкций глагола ищем, какие падежи могут идти после данного предлога, и сравниваем с падежами из строки. Если решение единственно, тогда берем его. Если же нет (такой вариант вообще существует?) выбираем падеж по некоторому приоритету.
Ø Если предлога нет, тогда это либо винительный падеж (основной предмет), либо творительный (дополнительный или вспомогательный предмет). Опять же просматриваем все конструкции глагола и пытаемся решить задачу. Если единственного решения нет (варианты таких команд есть, но какие-то бессмысленные), тогда выбираем винительный падеж.
v Ищем предмет, в котором присутствуют все названные имена.
Ø Нашли – возвращаем результат.
Ø Нет – ошибка, такого предмета в игровой базе нет.
Функция РасстановкаПредметов(Массив,Глагол)
Входящие данные: глагол и массив из функции РазделениеПредметов():
Предлог |
Количество |
Падеж |
Предмет в игровой базе |
Флаг наличия разделителя |
Результат: Массив вида:
Основной предмет |
Кол-во |
Предлог |
Дополнительный предмет |
Кол-во |
Предлог |
Вспомогательный предмет |
Кол-во |
Описание: функция должна разделить предметы на основной, дополнительный и вспомогательный, а так же определить их комбинации, с которыми будут потом совершаться действия. Каждый из таких вариантов заносится в массив.
Алгоритм:
v Если глагол непереходный, то есть основной предмет указывать не нужно, тогда нам важны только первый и пятый столбцы входящего массива (предлог и флаг разделителя):
предлог |
флаг разд. |
из |
0 |
в |
1 |
в |
1 |
в |
0 |
из |
0 |
Такая последовательность из предлогов и разделителей делится на части, каждая из которых имеет вид: (I)Предлог1 + [разделитель] + (II)[Предлог2 + разделитель + Предлог2 +разделитель...] + (III)[Предлог2]. То, что указано в квадратных скобках, может и не присутствовать. Почему выбран вариант с одним первым предлогом? Давайте сравним:
«Выстрелить из пушки по воробьям и по сорокам»
и
«Выстрелить из пушки и из винтовки по сорокам».
В первом случае, как бы произносящий не ставил ударение, ясно, что стрелять нужно по тем и другим. Во втором, если сделать акцент на «из пушки» и после этого выдержать паузу, получится, что из пушки нужно просто стрельнуть, а вот из винтовки уже по птичкам.
v Такая логика и привела к вышеупомянутой структуре. Как найти часть:
Ø (I) – берем, естественно, на эту роль первую строчку. Если есть разделитель, то часть сразу же закончена.
Ø (II) - все последующие строки с одинаковыми предлогами (отличными от первого, иначе – ошибка) и с разделителями.
Ø (III) – Если разделителя нет, а предлог совпадает с предыдущими, то он относится к первой части только в том случае, если дальше уже массив заканчивается. Иначе он становится началом для построения следующей части.
v Части найдены, можно уже распределить предметы и определить количество действий. Ясно, что предметы, которые идут с Предлогом1 составят дополнительные предметы и к каждому из них указывается набор вспомогательных предметов, то есть тех, которые идут с Предлогом2. Основного предмета не будет, т.к. глагол непереходный.
v С переходными глаголами всё немного сложнее. Здесь нужно поделить все предметы и предлоги на свои основные предметы, а дальше уже обработка каждой такой части совпадает с обработкой у непереходных глаголов.
v Основной предмет всегда в винительном падеже и без предлога. В таблице падеж и предлог указаны. Как будем делить: всё, до последнего разделителя между одним и другим основными предметами, относится к первому, оставшаяся часть – ко второму.
v Теперь можем заполнить результирующий массив.
Процедура АнализСтроки(Строка)
Входящие данные: строка, которая содержать команду игрока.
Описание: должна найти в строке несколько действий и поделить предметы между ними, а затем для каждой части вызвать функцию ПоискДействия().
Алгоритм:
v Между двумя глаголами отнесём к первому всё то, что идёт до последнего разделителя между ними. Остальное уйдёт ко второму.