2012-03-01 5 views
2

私は、alpha-betaプルーニングでミニマックスを使用してオセロエンジンを書いています。 それは大丈夫作業だが、私は次のような問題が見つかりました:アルゴリズムは、位置が失われたことを発見した場合Minimaxアルゴリズムが最良の移動を返さない

、予想通りそれは-INFINITYを返しますが、この場合 に私は「最良」の動きを追跡することができないんだけど...ポジションは既に失われていますが、有効な移動を返す必要があります(良いチェスエンジンがそうするように、より長く続く移動が望ましい)。

private float minimax(OthelloBoard board, OthelloMove best, float alpha, float beta, int depth) 
{    
    OthelloMove garbage = new OthelloMove();    
    int currentPlayer = board.getCurrentPlayer(); 

    if (board.checkEnd()) 
    {       
     int bd = board.countDiscs(OthelloBoard.BLACK); 
     int wd = board.countDiscs(OthelloBoard.WHITE); 

     if ((bd > wd) && currentPlayer == OthelloBoard.BLACK)     
      return INFINITY; 
     else if ((bd < wd) && currentPlayer == OthelloBoard.BLACK)       
      return -INFINITY;    
     else if ((bd > wd) && currentPlayer == OthelloBoard.WHITE)        
      return -INFINITY;    
     else if ((bd < wd) && currentPlayer == OthelloBoard.WHITE)        
      return INFINITY;    
     else        
      return 0.0f;    
    } 
    //search until the end? (true during end game phase) 
    if (!solveTillEnd) 
    { 
     if (depth == maxDepth) 
      return OthelloHeuristics.eval(currentPlayer, board); 
    } 

    ArrayList<OthelloMove> moves = board.getAllMoves(currentPlayer);    

    for (OthelloMove mv : moves) 
    {       
     board.makeMove(mv);    
     float score = - minimax(board, garbage, -beta, -alpha, depth + 1);   
     board.undoMove(mv);    

     if(score > alpha) 
     { 
      //Set Best move here 
      alpha = score;     
      best.setFlipSquares(mv.getFlipSquares()); 
      best.setIdx(mv.getIdx());   
      best.setPlayer(mv.getPlayer());        
     } 

     if (alpha >= beta) 
      break;     

    }     
    return alpha; 
} 

私が使用してそれを呼び出す:失われた位置は(それが例えば10の移動後失った想像する)場合

AI ai = new AI(board, maxDepth, solveTillEnd); 

//create empty (invalid) move to hold best move 
OthelloMove bestMove = new OthelloMove(); 
ai.bestFound = bestMove; 
ai.minimax(board, bestMove, -INFINITY, INFINITY, 0); 

//dipatch a Thread 
new Thread(ai).start(); 
//wait for thread to finish 

OthelloMove best = ai.bestFound(); 

を検索し、上記最良の変数が等しく、ここ

は、コードがあります引数として渡された空の無効な移動に...なぜ?

ありがとうございました!

+1

[faq]と[ask]を読んで、さらに具体的な質問をしてください。さらに、あなたの質問は不完全です。あなたは問題のかなり重要なクラス 'AI'の定義を示していません –

+0

問題は概念的であり、コードの問題ではありません。私が提供するコードは、私が考える問題を解くのに十分です。しかし、とにかくありがとう、私はもっと知るためにこれを読むでしょう。 – Fernando

答えて

3

あなたの問題は、勝敗スコアとして-INFINITYと+ INFINITYを使用していることです。勝敗のスコアは他の任意の評価スコアより高くても低くてもかまいませんが、あなたの無限の値と同じではありません。これは絶望的に失われたポジションでも選出されることを保証します。

+0

あなたはちょうど問題を解決しました、ありがとう!失われた位置に達するとINFINITY/10または-INFINITY/10が返されます。私がよく分かっていれば、私は-INFと+ INFの間の値を返さなければなりません、そうですか? – Fernando

+0

ポジションが勝ったり紛失した場合にのみ、それらの値を返すことができる限り、修正してください。 –

+0

あなたはまた、あなたが勝つか失うかに基づいて値を返すようにしなければならないので、64個で勝った場合、50個で勝った場合より大きな値を返します。この方法では、あなたのアルゴリズムは勝利を捜すだけでなく、最高の勝利を捜すでしょう。すべての勝利条件の値は、勝利条件が満たされていない場合の値より大きくする必要があります。 – user829876

2

私はminimaxを実装して以来長い時間がかかりましたので、間違っているかもしれませんが、あなたのコードは勝ち負けの動きに遭遇した場合、最良の変数を更新しません。(これはボード.checkEnd())文をメソッドの先頭に追加します)。

また、できるだけ多くのアルゴリズムで勝利しようとする、または勝てない場合にできるだけ多くのアルゴリズムを失いたくない場合は、評価関数を更新することをお勧めします。勝利状況では、大きな値(非勝利状況よりも大きい)を返す必要があります。負けた状況では、大きな負の値(負けていない状況よりも少ない)を返す必要があります。

あなたはあなたの評価関数をそのように更新し、(board.checkEnd())もしあなたのアルゴリズムがうまくいけば(それに他の問題がない限り)、チェックをスキップすると、 。がんばろう!

0

ポジションが本当に勝つか失われたかを知ることができれば、それはあなたがエンドゲームを解決していることを意味します。この場合、中間ゲームで評価する見積もりとは異なり、正確に計算できるので、評価関数はゲームの最終得点(合計勝利64、損失31)を返す必要があります。

関連する問題