ゲーム2048の戦略の比較

2048-2014年に登場し、人気のタイムキラーになりました。 ゲームの単純なルールは、プレイヤーにクローン、ボット、および勝利戦略を作成するようにのみプッシュします。 Habréを含む。 ( Clonebotstrategy )この記事では、ゲーム戦略を評価するための便利なツールと、複数のボットでどのように機能するかの例を説明します。







ゲームのスクリーンショット









ツール自体は3つの部分で構成されています。 1つはC ++エンジンです。 コンソールで手動で再生できます。 次のアルゴリズムに従って動作します。







  1. 競技場で2つのランダムなセルを選択し、それぞれにデュースを配置して、これらのセルの座標を表示します。







  2. プレイヤーがデッドロックの動き(プレイフィールドが変化しない後の動き)が行われるまで、エンジンはサイクルを実行します。







    1. プレーヤーの動きを読みます。
    2. 競技場でこの移動を実行します。
    3. 新しいランダム値(2つまたは4つ)が出現したセルの座標とこの値自体を印刷します。


  3. ゲームの最後に、移動数、スコア、ゲーム時間(ミリ秒)が表示されます。


競技場をシミュレートするために、エンジンはboard.hppのクラスを使用します。 コメント付きのこのクラスの宣言。







template<int n> class A{ //    n private: int left_adder(int&, int); // 16      move int left_compressor(int&, int); //     namespace int left_move_row(int); //    4   int left_move(); //      , int right_adder(int&, int); //         int right_compressor(int&, int); // int right_move_row(int); // int right_move(); // int up_adder(int&, int); // int up_compressor(int&, int); // int up_move_column(int); // int up_move(); // int down_adder(int&, int); // int down_compressor(int&, int); // int down_move_column(int); // int down_move(); // std::pair<int,int> random(); //         2  4 void out() const; //    a.    move(0) unsigned score = 0; //  bool deadlock = false; //       static std::mt19937 rand; //    std::array<std::array<int,n>,n> a; //       public: A(); // std::vector<int> init(); //            std::vector<int> move(int); //   unsigned get_score() const; //   };
      
      





2番目は、戦略を評価する必要があるボットです。 彼は、エンジンが出力する内容を読み取り(エンジンとボットのゲームフィールドを同期するため)、テスト中の戦略が最良と考える動きを表示します。 ボットは任意の言語で作成できます。 唯一の制限は、行き止まりの方向に移動できないことです。







3番目の部分は、最初の2つのコンポーネントを「接続」し、統計を読み取り可能な形式で表示する単純なbashスクリプトです。







ボットの例



4つのボットはすべて、 ボードモジュールを使用してPythonで記述されており、評価関数のみが異なります。 1つの引数が評価関数に渡されます-競技場の現在の状態。 競技場には、利用可能な動きを決定するデッドロックメソッドがあります。 主な機能はエンジンと通信します。







1.ランダム選択







ボットはランダムな動きを可能にします。 このボットは、その有効性を他のボットの有効性と比較するためだけに作成されています。







平均結果:1250







ソースコード
 import random import board def f(a): l = [1, 2, 3, 4] ans = random.choice(l) while a.deadlock(ans) and l != []: ans = random.choice(l) del l[l.index(ans)] if l == [] and a.deadlock(ans): ans = 0 return ans board.main(f)
      
      





2.円の動き







ボットは最初の移動を行い、次に行き止まりをスキップして時計回りに次の移動を選択します。







平均結果:2,900







ソースコード
 import board def f(a): global h ans = h % 4 + 1 while a.deadlock(ans) and ans != h: ans = ans % 4 + 1 h = ans return h h = 0 board.main(f)
      
      





3.すべてが1つのコーナーに







ボットは最初の上昇を行います。 上に移動するたびに、右への移動を選択し、右に移動するたびに上に移動します。 選択した動きがデッドロックの場合、ボットは前の動きを繰り返します。 前の動きが行き止まりの場合、ボットは左に移動しようとし、極端な場合は下に移動しようとします。







平均結果:3900







ソースコード
 import board def f(a): global h if h == 1: l = [2, 1] else: l = [1, 2] l += [4, 3, 0] while a.deadlock(l[0]) and l[0] != 0: l = l[1:] h = l[0] return h h = 0 board.main(f)
      
      





4.最大ポイント







このボットは、4つの方向すべての動きをチェックし、最大ポイントをもたらす方向を選択します。







平均結果:4000







ソースコード
 import board def f(a): max = 0 ans = 0 for i in range(1, 5): if not a.deadlock(i): b = a.copy() t = b.move(i) if (t >= max): ans = i max = t return ans board.main(f)
      
      





統計



すべてのボットが同じ条件下で1000回チェックされました。







ボット番号 平均 歩数 分 歩数 マックス 歩数 平均 アカウント 分 アカウント マックス アカウント 平均 時間 分 時間 マックス 時間
1 131 50 266 1259 240 3216 90 60 242
2 233 57 647 2885 292 11296 108 52 234
3 311 98 859 3905 740 14700 155 78 363
4 317 70 826 4027 412 13292 776 116 2692


Githubのすべてのソース








All Articles