- moveT MiniMax(stateT state)
- {
- moveT bestMove;
- max_move(state,bestMove);
- return bestMove;
- }
- int max_move(stateT state,int & bestMove)
- {
- int v = -10000;
- if(GameIsOver(state))
- {
- return EvaluateStaticPosition(state);
- }
- vector<moveT> moveList;
- GenerateMoveList(state,moveList);
- int nMoves = moveList.size();
- for(int i = 0 ; i < nMoves ; i++)
- {
- moveT move = moveList[i];
- MakeMove(state,move);
- int curValue = min_move(state,bestMove);
- if(curValue > v)
- {
- v = curValue;
- bestMove = move;
- }
- RetractMove(state,move);
- }
- return v;
- }
- int min_move(stateT state,int &bestMove)
- {
- int v = 10000;
- if(GameIsOver(state))
- {
- return EvaluateStaticPosition(state);
- }
- vector<moveT> moveList;
- GenerateMoveList(state,moveList);
- int nMoves = moveList.size();
- for(int i = 0 ; i < nMoves; i++)
- {
- moveT move = moveList[i];
- MakeMove(state,move);
- int curValue = max_move(state,depth+1,bestMove);
- if(curValue < v)
- {
- curValue = v;
- }
- RetractMove(state,move);
- }
- return v;
- }
P.S.:还有其他伪代码用于找到minmax值.然而,他们只专注于井字游戏,我试图将其扩展到其他游戏.谢谢.
更新:整个代码可以在这里找到:http://ideone.com/XPswCl
解决方法
由于第一和第二玩家都只关心第一个玩家的得分,因此EvaluateStaticPosition应该返回一个值,表明第一个玩家的棋盘状态有多好.轮到它是不相关的.
- int EvaluateStaticPosition(stateT state)
- {
- if(CheckForWin(state,FIRST_PLAYER))
- {
- return WINNING_POSITION;
- }
- if(CheckForWin(state,Opponent(FIRST_PLAYER)))
- {
- return LOSING_POSITION;
- }
- return NEUTRAL_POSITION;
- }
现在,当你想要对第一个玩家最好的移动时,请拨打MaxMove.如果您想要最适合第二个玩家的移动,请致电MinMove.
- moveT MiniMax(stateT state)
- {
- moveT bestMove;
- int i = 0;
- if (state.whoseTurn == FIRST_PLAYER){
- i = MaxMove(state,bestMove);
- }
- else{
- i = MinMove(state,bestMove);
- }
- cout<<"i is "<<i<<endl;
- return bestMove;
- }
最后,你在MinMove和MaxMove中遇到了一些问题.当你在任何一个中分配curRating时,你不应该将bestMove作为第二个参数传递给MaxMove或MinMove.然后它将把对手的最佳动作放入bestMove,这是没有意义的.相反,声明一个opponentsBestMove对象并将其作为第二个参数传递. (您实际上不会使用该对象,甚至不会在之后查看其值,但这没关系).通过该更改,您永远不会在MinMove中为bestMove分配任何内容,因此您应该在if(curRating< v)块内部执行此操作.
- int MaxMove(stateT state,moveT &bestMove)
- {
- if(GameIsOver(state))
- {
- return EvaluateStaticPosition(state);
- }
- vector<moveT> moveList;
- GenerateMoveList(state,moveList);
- int nMoves = moveList.size();
- int v = -1000;
- for(int i = 0 ;i<nMoves; i++)
- {
- moveT move = moveList[i];
- MakeMove(state,move);
- moveT opponentsBestMove;
- int curRating = MinMove(state,opponentsBestMove);
- if (curRating > v)
- {
- v = curRating;
- bestMove = move;
- }
- RetractMove(state,move);
- }
- return v;
- }
- int MinMove(stateT state,moveT &bestMove)
- {
- if(GameIsOver(state))
- {
- return EvaluateStaticPosition(state);
- }
- vector<moveT>moveList;
- GenerateMoveList(state,moveList);
- int nMoves = moveList.size();
- int v = 1000;
- for(int i = 0 ; i<nMoves; i++)
- {
- moveT move = moveList[i];
- MakeMove(state,move);
- moveT opponentsBestMove;
- int curRating = MaxMove(state,opponentsBestMove);
- if(curRating < v)
- {
- v = curRating;
- bestMove = move;
- }
- RetractMove(state,move);
- }
- return v;
- }
此时你应该有一个无与伦比的AI!
- The final position looks like this:
- O | O | X
- ---+---+---
- X | X | O
- ---+---+---
- O | X | X
- Cat's game.
另一种方法利用了tic-tac-toe是零和游戏的事实.换句话说,在游戏结束时,玩家的得分总和将等于零.对于双人游戏,这意味着一个玩家的得分将始终是另一个玩家的得分.这对我们来说很方便,因为最小化其他玩家的分数与最大化自己的分数相同.因此,不是一个玩家最大化他的分数而一个玩家最小化另一个玩家的分数,我们可以让两个玩家都试图最大化他们自己的分数.
将EvaluateStaticPosition更改回其原始形式,以便根据当前玩家的棋盘状态有多好而得分.
- int EvaluateStaticPosition(stateT state)
- {
- if(CheckForWin(state,state.whoseTurn))
- {
- return WINNING_POSITION;
- }
- if(CheckForWin(state,Opponent(state.whoseTurn)))
- {
- return LOSING_POSITION;
- }
- return NEUTRAL_POSITION;
- }
删除MinMove,因为我们只关心最大化.
重写MaxMove,以便选择让对手得分最差的移动.最佳动作的得分是其他球员最差得分的负值.
- int MaxMove(stateT state,moveT &bestMove)
- {
- if(GameIsOver(state))
- {
- return EvaluateStaticPosition(state);
- }
- vector<moveT> moveList;
- GenerateMoveList(state,move);
- moveT opponentsBestMove;
- int curRating = -MaxMove(state,move);
- }
- return v;
- }
由于MaxMove用于两个玩家,我们不再需要区分MiniMax功能中的玩家.
- moveT MiniMax(stateT state)
- {
- moveT bestMove;
- int i = 0;
- i = MaxMove(state,bestMove);
- cout<<"i is "<<i<<endl;
- return bestMove;
- }