有没有任何一种“表达类”(C ++)

时间:2009-06-10 21:27:39

标签: c++ expression

我正在创建一个游戏,让玩家输入输入,更改某些状态,然后检查“目标值”是否为真(显然这个描述非常简化),我希望能够让目标值为如果玩家的生命低于某个值,则剩余的敌人数量等于零。是否有任何“表达式类”可以保存一个简单的“value1比较运算符值2”并检查它?即:

expression goal(x = 4);

如果没有,是否有人建议如何开发表达式类?

编辑:另一个(更倾向于我想要实现的目标)示例:

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); };

9 个答案:

答案 0 :(得分:22)

动态表达

如果你想从用户那里收到一个字符串并从中构建一个表达式,那么C++ Mathematical Expression Library可能适合你的账单吗?

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);
   }
}

还有可能嵌入脚本语言,例如LuaPython,这将为您提供(甚至)更多的权力。如果您正在编写游戏,则需要考虑这一点,因为您可能希望编写大部分内容。

如果您正在使用Qt,则可以使用QtScript(Javascript-ish)运行从QObject派生对象中读取(静态或动态)属性的表达式。

使用上述之一可以让您不必编写自己的解析器,AST和评估程序,但是对于一小组操作符,如果使用Boost.Spirit或某些操作符,则不应该太难解决某些问题其他不错的解析库。

静态表达

要在一组预定义表达式之间进行选择(即在编译时已知),您应该将表达式存储在多态函数对象中。

对于C ++ 11,如果可以使用,请使用std::function和lambda表达式。

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

对于早期的编译器,我建议在Boost(boost::)或C ++ 0x TR1(std::)中使用function和bind,具体取决于你的编译器。此外,Boost.Lambda将在这里提供帮助,因为它允许您构造和存储表达式以供以后评估。但是,如果您不熟悉C ++和模板(或函数式编程),它可能会让您感到非常恐慌。

你可以写

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);

使用bind,它看起来像:

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(); }

答案 1 :(得分:1)

在运行时期间没有标准的方法来编译表达式。你必须以其他方式做到这一点。

您可以考虑使用脚本语言,如Lua或Python,并将其嵌入到C ++中。这将使您的玩家能够按照您希望的程度进行编程。

答案 2 :(得分:0)

不,没有那样的东西。也许表达式类有点过于抽象。如何使用IsReached()方法定义各种Goal类?

答案 3 :(得分:0)

C ++没有将此作为语言的一部分 - 在运行时无法访问解析程序的相同内容。

我确信你可以使用许多第三方算术解析器库。

答案 4 :(得分:0)

我想你可以定义自己的类并使用'assert'关键字来解决,但我可能已经理解了这个问题。

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

答案 5 :(得分:0)

为什么不建立自己的表达式类?

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;
}

其他类可以有其他方法,参数,运算符等。运用你的想象力。

答案 6 :(得分:0)

在C ++中没有标准的方法。一种解决方案是编写自己的解析器。

另一个解决方案,我建议:在程序中嵌入Lua解释器。 Lua是一种简单但功能强大的编程语言,它还具有极轻量级(<300kB)且易于使用的解释器。在此处阅读介绍性文章:http://www.ibm.com/developerworks/linux/library/l-embed-lua/index.html

在游戏中嵌入Lua有许多不错的优势:

  • 你可以把它当作一个强大的 游戏的配置语言
  • 和Lua,你 可以轻松创建命令行 互动环境,这是 非常适合测试和体验。例如,你会的 能够改变游戏引擎 参数并查看效果 立即,无需重新编译。这对于“研究”项目或游戏编程特别方便。

答案 7 :(得分:0)

静态表达

Macke帖子的修正案)

当您的表达式在编译时已知时,您可以使用std::function。但是,性能可能不是最佳的。

您可以在编译时自动注册测试,并使用C ++ 11模板和宏在运行时使用(presumambly)最小运行时开销执行它们。可以找到概念验证实现here

从长远来看,名为“Contracts”的语言功能可以胜任。 (N4415N4435N4378)今天,有各种库可用于支持合同编程。

答案 8 :(得分:-3)

似乎没有那么多公认的C ++表达式评估库。我为CSVfix编写了自己的文件,您可以通过查看构成CSVfix源代码一部分的ALib库中的a_expr.ha_expr.cpp文件来查看。评估员没有太多推荐自己,除了它完成工作并且(恕我直言)相当容易理解。

不幸的是,目前没有评估人员的公开文档,根据我自己的经验法则,未记录的内容无法重复使用。但是,单元测试显示了它是如何使用的,如果想象的话,源代码可能会给你一些关于实现自己的评估器的想法。