20

プレイヤーが入力を入力し、いくつかの状態を変更してから、「目標値」が真であるかどうかを確認するゲームを作成しています (明らかに、この説明は非常に単純化されています)。残りの敵の数がゼロに等しい場合、プレイヤーのライフは特定の値を下回っています。単純な「value1比較演算子value2」を保持してチェックできる「式クラス」はありますか? すなわち:

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

9 に答える 9

24

動的表現

ユーザーから文字列を受け取り、そこから式を作成したい場合は、C++ 数式ライブラリが適しているのではないでしょうか?

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 っぽい) を使用して、QObject 派生オブジェクトから (静的または動的) プロパティを読み取る式を実行できます。

上記のいずれかを使用すると、独自のパーサー、AST、およびエバリュエーターを作成する必要がなくなりますが、少数のオペレーターのセットの場合、Boost.Spiritまたは他の適切な解析ライブラリを使用すれば、何かを一緒にハックするのはそれほど難しくありません。

静的式

定義済みの式 (つまり、コンパイル時に既知) のセットから選択するには、式を多相関数オブジェクトに格納する必要があります。

C++11 の場合、利用可能な場合はstd::function、ラムダ式を使用します。

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

以前のコンパイラでは、コンパイラに応じて、 Boost (boost::) または C++0x TR1 (std::)のいずれかで関数とバインドを行うことをお勧めします。また、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);

バインドすると、次のようになります。

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(); }
于 2009-06-10T21:37:09.873 に答える
1

実行時に式をコンパイルする標準的な方法はありません。他の方法で行う必要があります。

Lua や Python などのスクリプト言語を使用して、C++ に埋め込むことを検討してください。これにより、プレーヤーは、必要な範囲でプログラミングできるようになります。

于 2009-06-10T22:00:49.267 に答える
0

C++ でそれを行う標準的な方法はありません。1 つの解決策は、独自のパーサーを作成することです。

私がお勧めするもう 1 つの解決策は、プログラムに Lua インタープリターを埋め込むことです。Lua はシンプルで強力なプログラミング言語であり、非常に軽量 (<300kB) で使いやすいインタープリターも備えています。こちらの入門記事をお読みください: http://www.ibm.com/developerworks/linux/library/l-embed-lua/index.html

Lua をゲームに組み込むことには、いくつかの利点があります。

  • ゲームの強力な構成言語として使用できます
  • Lua を使用すると、コマンドラインで対話型の環境を簡単に作成でき、テストや実験に適しています。たとえば、ゲーム エンジンのパラメーターを変更して、再コンパイルせずにすぐに効果を確認できます。これは、「研究」プロジェクトやゲーム プログラミングに特に便利です。
于 2009-06-10T22:15:59.827 に答える
0

いいえ、そんなことはありません。おそらく、式クラスは少し抽象的すぎます。IsReached() メソッドでさまざまな Goal クラスを定義するのはどうですか?

于 2009-06-10T21:34:39.117 に答える
0

C++ には言語の一部としてこれがありません。実行時に、プログラムを解析したものと同じものにアクセスする方法はありません。

ただし、使用できるサードパーティの算術パーサー ライブラリは多数あると思います。

于 2009-06-10T21:35:13.747 に答える
0

独自のクラスを定義し、「assert」キーワードを使用して回避できると思いますが、質問を間違って理解した可能性があります。

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

于 2009-06-10T21:37:10.653 に答える
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;
}

他のクラスには、他のメソッド、パラメーター、演算子などを含めることができます。想像力を働かせてください。

于 2009-06-10T21:49:19.973 に答える
-3

C++ 用の認識された式評価ライブラリはそれほど多くないようです。CSVfix ソースの一部を形成する ALib ライブラリ内のおよびファイルを参照することで理解できる CSVfixに独自に作成しました。評価者は、それが仕事をし、(IMHO) 理解するのがかなり簡単であることを除いて、それ自体を推奨することはあまりありません。a_expr.ha_expr.cpp

残念なことに、現在、評価者のための公開文書はなく、私自身の経験則によれば、文書化されていないものは再利用できません。ただし、単体テストはそれがどのように使用されるかを示しており、ソースはあなた自身のエバリュエーターを実装するためのいくつかのアイデアを提供するかもしれません.

于 2009-06-10T21:55:50.803 に答える