Return bestMoveax算法中的tictactoe [英] Return bestMove in minimax algorithm for tictactoe
问题描述
我曾试图在Russel Norvig的人工智能书中给出井字游戏的minimax算法。它有一切,除了的方式返回bestMove到用户。我想努力回报bestMove,但不能决定什么时候选择bestMove。帮助,任何人?
I have tried to code the minimax algorithm for tic-tac-toe given in Russel Norvig's book on Artificial Intelligence. It had everything except that the way to return the bestMove to the user. I am trying hard to return the bestMove, but cannot decide when to choose the bestMove. Help, anyone?
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值。然而,他们只专注于tic-tac-toe,我试图将它扩展到其他游戏。非常感谢。
P.S.: There are other pseudocode for finding the minmax value. However, they are focused on tic-tac-toe only, I am trying to extend it to other games. Thanks.
更新:整个代码可以在这里找到: http: //ideone.com/XPswCl
Update : The whole code can be found here : http://ideone.com/XPswCl
推荐答案
在minimax的最简单版本中,得分,并且第二玩家希望最小化第一玩家的得分。
由于第一个和第二个玩家只关心第一个玩家的分数, EvaluateStaticPosition
应该返回一个值,表示第一个玩家的棋盘状态有多好。这是不相关的。
In the simplest version of minimax, the first player wishes to maximize his score, and the second player wishes to minimize the first player's score.
Since both first and second player only care about the first player's score, EvaluateStaticPosition
should return a value indicating how good the board state is for the first player. Whose turn it is is not relevant.
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 。
Now, when you want the move that's best for the first player, call MaxMove. When you want the move that's best for the second player, call 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
对象,并将其作为第二个参数。 (你实际上不会使用对象,或者甚至查看它的值,但是没关系)。有了这个改变,你从不会分配任何东西给 bestMove
在 MinMove
,所以你应该在 if(curRating< v)
block。
Finally, you have some problems inside of MinMove
and MaxMove
. when you assign curRating
in either one, you shouldn't pass in bestMove
as the second argument to MaxMove
or MinMove
. It will then put the opponent's best move into bestMove
, which doesn't make sense. Instead, declare an opponentsBestMove
object and pass that as the second argument. (You won't actually be using the object or even looking at its value afterwards, but that's ok). With that change, you never assign anything to bestMove
within MinMove
, so you should do so inside the if(curRating < v)
block.
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!
At this point you should have an unbeatable AI!
The final position looks like this:
O | O | X
---+---+---
X | X | O
---+---+---
O | X | X
Cat's game.
另一种方法利用了tic-tac-toe是一个零和游戏的事实。换句话说,在游戏结束时,玩家的得分的总和将等于零。对于双玩家游戏,这意味着一个玩家的得分总是为其他玩家的得分。这对我们很方便,因为最小化其他玩家的分数然后等于最大化自己的分数。因此,不是一个玩家最大化他的得分和一个玩家最小化另一个玩家的得分,我们可以让两个玩家尝试最大化自己的得分。
An alternative method takes advantage of the fact that tic-tac-toe is a zero-sum game. In other words, at the end of the game, the sum of the scores of the players will equal zero. For a two player game, this means that one player's score will always be the negative of the other player's. This is convenient for us, since minimizing the other player's score is then identical to maximizing one's own score. So instead of one player maximizing his score and one player minimizing the other player's score, we can just have both players attempt to maximize their own score.
更改 EvaluateStaticPosition
回到其原始形式,以便根据当前播放器的板状态有多好来给出分数。
Change EvaluateStaticPosition
back to its original form, so that it gives a score based on how good the board state is for the current player.
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
,以便它选择给予对手最差可能得分的移动。
Delete MinMove
, since we only care about maximizing.
Rewrite MaxMove
so that it chooses the move that gives the opponent the worst possible score. The score for the best move is the negative of the other player's worst score.
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 = -MaxMove(state, opponentsBestMove);
if (curRating > v)
{
v = curRating;
bestMove = move;
}
RetractMove(state, move);
}
return v;
}
由于 MaxMove
用于两个玩家,我们不再需要区分 MiniMax
函数中的玩家。
Since MaxMove
is used for both players, we no longer need to distinguish among players in the MiniMax
function.
moveT MiniMax(stateT state)
{
moveT bestMove;
int i = 0;
i = MaxMove(state, bestMove);
cout<<"i is "<<i<<endl;
return bestMove;
}
这篇关于Return bestMoveax算法中的tictactoe的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!