我正在创建一个游戏,让玩家输入输入,更改某些状态,然后检查“目标值”是否为真(显然这个描述非常简化),我希望能够让目标值为如果玩家的生命低于某个值,则剩余的敌人数量等于零。是否有任何“表达式类”可以保存一个简单的“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); };
答案 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);
}
}
还有可能嵌入脚本语言,例如Lua或Python,这将为您提供(甚至)更多的权力。如果您正在编写游戏,则需要考虑这一点,因为您可能希望编写大部分内容。
如果您正在使用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'关键字来解决,但我可能已经理解了这个问题。
答案 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有许多不错的优势:
答案 7 :(得分:0)
静态表达
(Macke帖子的修正案)
当您的表达式在编译时已知时,您可以使用std::function
。但是,性能可能不是最佳的。
您可以在编译时自动注册测试,并使用C ++ 11模板和宏在运行时使用(presumambly)最小运行时开销执行它们。可以找到概念验证实现here。
从长远来看,名为“Contracts”的语言功能可以胜任。 (N4415,N4435,N4378)今天,有各种库可用于支持合同编程。
答案 8 :(得分:-3)
似乎没有那么多公认的C ++表达式评估库。我为CSVfix编写了自己的文件,您可以通过查看构成CSVfix源代码一部分的ALib库中的a_expr.h
和a_expr.cpp
文件来查看。评估员没有太多推荐自己,除了它完成工作并且(恕我直言)相当容易理解。
不幸的是,目前没有评估人员的公开文档,根据我自己的经验法则,未记录的内容无法重复使用。但是,单元测试显示了它是如何使用的,如果想象的话,源代码可能会给你一些关于实现自己的评估器的想法。