Элегантный синтаксический анализ команд в текстовой игре на основе ООП - PullRequest
8 голосов
/ 05 февраля 2010

Я играю с написанием MUD / текстового приключения (пожалуйста, не смейтесь) на Ruby. Кто-нибудь может дать мне какие-нибудь советы по поводу элегантного, основанного на oop решения для анализа входного текста?

Здесь мы говорим ни о чем более сложном, чем «положить палочку на стол». Но все должно быть мягким; Хочу безболезненно продлить набор команд позже.

Мои текущие мысли, немного упрощенные:

  1. Каждый класс предметов (коробка, стол, комната, игрок) знает, как распознать команду, которая ему «принадлежит».

  2. Класс игры понимает своего рода предметно-ориентированный язык, включающий такие действия, как «переместить объект X внутрь объекта Y», «показать описание объекта X» и т. Д.

  3. Класс игры спрашивает каждый предмет в комнате, распознает ли он входную команду. Сначала скажи да победит.

  4. Затем он передает управление методу в классе элементов, который обрабатывает команду. Этот метод перефразирует команду в DSL, передает ее обратно игровому объекту, чтобы это произошло.

Должны быть изношенные, элегантные способы сделать это. Хотя, похоже, ничего не могу погуглить.

Ответы [ 5 ]

3 голосов
/ 05 февраля 2010

Шаблон проектирования Интерпретатор является наиболее объектно-ориентированным подходом к анализу, который я знаю, но я уверен, что эксперты по компилятору укажут алгоритмы, которые являются более мощными .

2 голосов
/ 05 февраля 2010

Похоже, вам нужен парсер.

Разбить входную строку на токены (слова). Затем подайте токены по одному на конечный автомат. Я нахожу, что автомат с нажатием вниз является довольно интуитивным и мощным способом написания такого stm.

1 голос
/ 05 февраля 2010

Для командных интерпретаторов мне нравится этот простой, а не элегантный шаблон. Шаблоны в динамических языках обычно содержат меньше блоков и строк, чем шаблоны GOF.

class Thing

  # Handle a command by calling the method "cmd_" + command.
  # Raise BadCommand exception if there is no method for that command.

  def handle_command(command, args)
    method_name = "cmd_#{command}"
    raise BadCommand, command unless respond_to?(method_name)
    send(method_name, args)
  end

  def cmd_quit(args)
    # the code for command "quit"
  end

  def cmd_list(args)
    # the code for command "list"
  end

  ...

end

Таким образом, добавление новой команды - это просто добавление нового метода. Нет необходимости корректировать таблицы или описания дел.

0 голосов
/ 05 февраля 2010

Хорошо. Так тебе нужна семантика? (поворот - это действие, зажечь объект, аргумент ... (я имею в виду ваш комментарий к dbemerlin)).

Почему бы не определить грамматику? хм ... я думаю, что lex и yacc не вариант? (поскольку это вовсе не ООП, но вам нужно «скомпилировать» пользовательский ввод для создания чего-либо - выполнения некоторого кода, который изменяет данные комнаты и выдает результат)

У вас может быть дизайн ООП для вашего объекта и его действия (например, у всех объектов есть метод .describeMe () ..), а также анализатор ввода + компилятор.

Я совершенно не в теме?

Редактировать: после просмотра паттерна интерпретации, на который указал Марк Симан, кажется, что это путь к тому, чтобы вы захотели его в ООП. (но вы несколько заново изобретете колесо)

0 голосов
/ 05 февраля 2010

Разделите его на токены, так как формат всегда будет:
[команда] [объект1] ([ссылка] [объект2])

Вы можете вызвать метод [команда] для [объект1] всвою комнату и передайте ей [object2], если применимо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...