c – 为tictactoe返回minimax算法中的bestMove

前端之家收集整理的这篇文章主要介绍了c – 为tictactoe返回minimax算法中的bestMove前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我试图在Russel Norvig的人工智能书中给出了用于井字游戏的极小极大算法.它拥有除了将bestMove返回给用户的方式之外的所有内容.我努力回归bestMove,但无法决定何时选择bestMove.帮忙,有人吗?
  1. moveT MiniMax(stateT state)
  2. {
  3. moveT bestMove;
  4.  
  5. max_move(state,bestMove);
  6.  
  7. return bestMove;
  8.  
  9. }
  10.  
  11. int max_move(stateT state,int & bestMove)
  12. {
  13. int v = -10000;
  14. if(GameIsOver(state))
  15. {
  16. return EvaluateStaticPosition(state);
  17.  
  18. }
  19.  
  20. vector<moveT> moveList;
  21. GenerateMoveList(state,moveList);
  22. int nMoves = moveList.size();
  23.  
  24. for(int i = 0 ; i < nMoves ; i++)
  25. {
  26. moveT move = moveList[i];
  27. MakeMove(state,move);
  28.  
  29. int curValue = min_move(state,bestMove);
  30.  
  31. if(curValue > v)
  32. {
  33. v = curValue;
  34. bestMove = move;
  35. }
  36. RetractMove(state,move);
  37.  
  38. }
  39.  
  40. return v;
  41.  
  42. }
  43.  
  44. int min_move(stateT state,int &bestMove)
  45. {
  46. int v = 10000;
  47. if(GameIsOver(state))
  48. {
  49. return EvaluateStaticPosition(state);
  50.  
  51. }
  52. vector<moveT> moveList;
  53. GenerateMoveList(state,moveList);
  54.  
  55. int nMoves = moveList.size();
  56.  
  57. for(int i = 0 ; i < nMoves; i++)
  58. {
  59. moveT move = moveList[i];
  60. MakeMove(state,move);
  61.  
  62. int curValue = max_move(state,depth+1,bestMove);
  63.  
  64. if(curValue < v)
  65. {
  66. curValue = v;
  67. }
  68. RetractMove(state,move);
  69.  
  70. }
  71. return v;
  72. }

P.S.:还有其他伪代码用于找到minmax值.然而,他们只专注于井字游戏,我试图将其扩展到其他游戏.谢谢.

更新:整个代码可以在这里找到:http://ideone.com/XPswCl

解决方法

在最简单的minimax版本中,第一个玩家希望最大化他的分数,第二个玩家希望最小化第一个玩家的分数.
由于第一和第二玩家都只关心第一个玩家的得分,因此EvaluateStaticPosition应该返回一个值,表明第一个玩家的棋盘状态有多好.轮到它是不相关的.
  1. int EvaluateStaticPosition(stateT state)
  2. {
  3. if(CheckForWin(state,FIRST_PLAYER))
  4. {
  5. return WINNING_POSITION;
  6. }
  7. if(CheckForWin(state,Opponent(FIRST_PLAYER)))
  8. {
  9. return LOSING_POSITION;
  10. }
  11. return NEUTRAL_POSITION;
  12. }

现在,当你想要对第一个玩家最好的移动时,请拨打MaxMove.如果您想要最适合第二个玩家的移动,请致电MinMove.

  1. moveT MiniMax(stateT state)
  2. {
  3. moveT bestMove;
  4. int i = 0;
  5. if (state.whoseTurn == FIRST_PLAYER){
  6. i = MaxMove(state,bestMove);
  7. }
  8. else{
  9. i = MinMove(state,bestMove);
  10. }
  11. cout<<"i is "<<i<<endl;
  12. return bestMove;
  13. }

最后,你在MinMove和MaxMove中遇到了一些问题.当你在任何一个中分配curRating时,你不应该将bestMove作为第二个参数传递给MaxMove或MinMove.然后它将把对手的最佳动作放入bestMove,这是没有意义的.相反,声明一个opponentsBestMove对象并将其作为第二个参数传递. (您实际上不会使用该对象,甚至不会在之后查看其值,但这没关系).通过该更改,您永远不会在MinMove中为bestMove分配任何内容,因此您应该在if(curRating< v)块内部执行此操作.

  1. int MaxMove(stateT state,moveT &bestMove)
  2. {
  3. if(GameIsOver(state))
  4. {
  5. return EvaluateStaticPosition(state);
  6. }
  7. vector<moveT> moveList;
  8. GenerateMoveList(state,moveList);
  9. int nMoves = moveList.size();
  10. int v = -1000;
  11. for(int i = 0 ;i<nMoves; i++)
  12. {
  13. moveT move = moveList[i];
  14. MakeMove(state,move);
  15. moveT opponentsBestMove;
  16. int curRating = MinMove(state,opponentsBestMove);
  17. if (curRating > v)
  18. {
  19. v = curRating;
  20. bestMove = move;
  21. }
  22. RetractMove(state,move);
  23. }
  24. return v;
  25.  
  26. }
  27. int MinMove(stateT state,moveT &bestMove)
  28. {
  29. if(GameIsOver(state))
  30. {
  31. return EvaluateStaticPosition(state);
  32. }
  33. vector<moveT>moveList;
  34. GenerateMoveList(state,moveList);
  35. int nMoves = moveList.size();
  36. int v = 1000;
  37. for(int i = 0 ; i<nMoves; i++)
  38. {
  39. moveT move = moveList[i];
  40. MakeMove(state,move);
  41. moveT opponentsBestMove;
  42. int curRating = MaxMove(state,opponentsBestMove);
  43. if(curRating < v)
  44. {
  45. v = curRating;
  46. bestMove = move;
  47. }
  48. RetractMove(state,move);
  49. }
  50. return v;
  51. }

此时你应该有一个无与伦比的AI!

  1. The final position looks like this:
  2.  
  3. O | O | X
  4. ---+---+---
  5. X | X | O
  6. ---+---+---
  7. O | X | X
  8.  
  9. Cat's game.

另一种方法利用了tic-tac-toe是零和游戏的事实.换句话说,在游戏结束时,玩家的得分总和将等于零.对于双人游戏,这意味着一个玩家的得分将始终是另一个玩家的得分.这对我们来说很方便,因为最小化其他玩家的分数与最大化自己的分数相同.因此,不是一个玩家最大化他的分数而一个玩家最小化另一个玩家的分数,我们可以让两个玩家都试图最大化他们自己的分数.

将EvaluateStaticPosition更改回其原始形式,以便根据当前玩家的棋盘状态有多好而得分.

  1. int EvaluateStaticPosition(stateT state)
  2. {
  3. if(CheckForWin(state,state.whoseTurn))
  4. {
  5. return WINNING_POSITION;
  6. }
  7. if(CheckForWin(state,Opponent(state.whoseTurn)))
  8. {
  9. return LOSING_POSITION;
  10. }
  11. return NEUTRAL_POSITION;
  12. }

删除MinMove,因为我们只关心最大化.
重写MaxMove,以便选择让对手得分最差的移动.最佳动作的得分是其他球员最差得分的负值.

  1. int MaxMove(stateT state,moveT &bestMove)
  2. {
  3. if(GameIsOver(state))
  4. {
  5. return EvaluateStaticPosition(state);
  6. }
  7. vector<moveT> moveList;
  8. GenerateMoveList(state,move);
  9. moveT opponentsBestMove;
  10. int curRating = -MaxMove(state,move);
  11. }
  12. return v;
  13.  
  14. }

由于MaxMove用于两个玩家,我们不再需要区分MiniMax功能中的玩家.

  1. moveT MiniMax(stateT state)
  2. {
  3. moveT bestMove;
  4. int i = 0;
  5. i = MaxMove(state,bestMove);
  6. cout<<"i is "<<i<<endl;
  7. return bestMove;
  8. }

猜你在找的C&C++相关文章