Подтвердить что ты не робот

Существует ли какой-либо "класс выражения" (С++)

Я создаю игру, которая позволяет игроку вводить ввод, изменяет некоторые состояния, а затем проверяет, истинно ли значение цели (очевидно, это описание значительно упрощено), и я хочу, чтобы это значение цели было ничего, если жизнь игроков ниже определенного значения, если количество оставшихся врагов равно нулю. Есть ли какой-либо "класс выражения", который может содержать простой "value1 compare-operator value2" и проверить его? т.е.:

expression goal(x = 4);

Если нет, есть ли у кого-нибудь какие-либо предложения относительно того, как я мог бы разработать класс выражения?

EDIT: еще один (более того, чего я пытаюсь достичь):

game.init(){ expression goal = FileRead(goalfile); }
game.checkstate(){ if(goal) exit(1); } //exit 1 is the games win state

//another more specific eg.:
class level1 { public: expression goal(total_enemies == 0); };
class level2 { public: expression goal(player.x == goal.x && player.y == goal.y); };
4b9b3361

Ответ 1

Динамические выражения

Если вы хотите получить строку от пользователя и построили выражение из этого, возможно, С++ Математическая библиотека выражений соответствует вашему счету?

template<typename T>
void trig_function()
{
   std::string expression_string = "clamp(-1.0,sin(2 * pi * x) + cos(x / 2 * pi),+1.0)";
   T x;
   exprtk::symbol_table<T> symbol_table;
   symbol_table.add_variable("x",x);
   symbol_table.add_constants();

   exprtk::expression<T> expression;
   expression.register_symbol_table(symbol_table);

   exprtk::parser<T> parser;
   parser.compile(expression_string,expression);

   for (x = T(-5.0); x <= T(+5.0); x += 0.001)
   {
      T y = expression.value();
      printf("%19.15f\t%19.15f\n",x,y);
   }
}

Есть также возможность встроить язык сценариев, например Lua или Python, что даст вам (даже) большую мощность. Это то, что нужно учитывать, если вы пишете игру, так как вы, скорее всего, захотите script больших ее частей.

Если вы используете Qt, вы можете использовать QtScript (Javascript-ish) для запуска выражений, которые читают (статические или динамические) свойства из объектов, полученных из QObject.

Используя одно из приведенных выше, вы не должны писать свой собственный парсер, АСТ и оценщик, однако для небольшого набора операторов не должно быть слишком сложно взломать что-то, если вы используете Boost.Spirit или какая-то другая достойная библиотека синтаксического анализа.

Статические выражения

Для выбора между набором предопределенных выражений (т.е. известным во время компиляции) вы должны сохранить выражение в объекте полиморфной функции.

Для С++ 11, если это доступно вам, используйте выражения std::function и лямбда.

std::function<bool (int, int)> expr = [](int a, int b) { a*2 < b };

Для более ранних компиляторов я рекомендую функцию и bind, либо в Boost (boost::) или С++ 0x TR1 (std::), в зависимости от вашего компилятора. Кроме того, Boost.Lambda будет полезен здесь, поскольку он позволяет создавать и хранить выражения для последующей оценки. Однако, если вы не знакомы с С++ и шаблонами (или функциональным программированием), это, вероятно, немного напугает вас.

С этим вы могли бы написать

using namespace boost::lambda;
boost::function<bool (int, int)> myexpr1 = (_1 + _2) > 20;
boost::function<bool (int, int)> myexpr2 = (_1 * _2) > 42;
std::cout << myexpr1(4,7) << " " << myexpr2(2,5);

со связью, это будет выглядеть так:

boost::function<bool (Player&)> check = bind(&Player::getHealth, _1) > 20;
Player p1;
if (check(p1)) { dostuff(); }

check = bind(&Player::getGold, _1) < 42;
if (check(p1)) { doOtherStuff(); }

Ответ 2

Нет стандартного способа компиляции выражений во время выполнения. Вам придется сделать это по-другому.

Вы можете использовать язык сценариев, например Lua или Python, и вставлять его в свой С++. Это позволит вашим игрокам программировать в той мере, в какой вы хотите.

Ответ 3

Нет, нет ничего подобного. Возможно, класс выражения является слишком абстрактным. Как определить различные классы целей с помощью метода IsReached()?

Ответ 4

С++ не имеет этого как часть языка - во время выполнения нет доступа к тому же материалу, который анализировал вашу программу.

Я уверен, что есть множество сторонних арифметических парсерных библиотек, которые вы могли бы использовать.

Ответ 5

Я думаю, вы можете определить свой собственный класс и работать с использованием ключевого слова 'assert', но я, возможно, понял этот вопрос неправильно.

http://www.cplusplus.com/reference/clibrary/cassert/assert/

Ответ 6

Почему бы не создать собственные классы выражений?

class GoalBase
{
    virtual bool goal() = 0;
};

class Enemies : public GoalBase 
{
   // ..
   private:
      int enemies_;

   public:
      Enemies(int start) : enemies_(start) {}
      void kill() { if (enemies_) --enemies_; }
      bool goal() { return enemies_ == 0; }
};

int main()
{
    Enemies enemiesToKill(5);
    enemiesToKill.kill();    

    // ..
    if (enemiesToKill.goal()) {
        // ..
    }

    return 0;
}

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

Ответ 7

Нет стандартного способа сделать это на С++. Одно из решений - написать собственный синтаксический анализатор.

Другое решение, которое я бы рекомендовал: встроить Lua-интерпретатор в вашу программу. Lua - простой, но мощный язык программирования, который также имеет чрезвычайно легкий (< 300 КБ) и простой в использовании интерпретатор. Прочтите вступительную статью здесь: http://www.ibm.com/developerworks/linux/library/l-embed-lua/index.html

У Lua, встроенного в вашу игру, есть ряд хороших побочных преимуществ:

  • вы можете использовать его как мощный язык конфигурации для вашей игры
  • с Lua, вы может легко создать командную строку интерактивной среды, хорошо для тестирования и экспериментов. Например, вы быть в состоянии изменить игровой движок параметров и увидеть эффект немедленно, без перекомпиляции. Это особенно удобно для "исследовательских" проектов или игрового программирования.

Ответ 8

Статические выражения

(поправка на Macke)

Когда ваши выражения известны во время компиляции, вы можете использовать std::function. Однако производительность может оказаться не оптимальной.

Вы можете автоматически регистрировать тест во время компиляции и выполнять их во время выполнения с (предположительно) минимальными затратами времени исполнения, используя шаблоны и макросы С++ 11. Реализация концептуальной концепции можно найти здесь.

В конечном счете функция языка, названная "" Контракты ", могла бы выполнить эту работу. ( N4415, N4435, N4378) Сегодня для поддержки контрактного программирования существуют различные библиотеки.

Ответ 9

Кажется, что не так много признанных библиотек оценки выражений для С++. Я написал свой собственный для CSVfix, который вы можете посмотреть, просмотрев файлы a_expr.h и a_expr.cpp в библиотеке ALib, которая формирует часть источника CSVfix. Оценщику нечего рекомендовать, за исключением того, что он выполняет свою работу и (ИМХО) достаточно прост для понимания.

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