C++极小极大函数
我已经在 Google 和 Stackoverflow 上搜索了这个问题,但我仍然不明白 minimax 函数是如何工作的。
我发现维基百科条目有该函数的伪代码版本:
function integer minimax(node, depth)
if node is a terminal node or depth <= 0:
return the heuristic value of node
α = -∞
for child in node: # evaluation is identical for both players
α = max(α, -minimax(child, depth-1))
return α
我通过 Google 找到的其他几个 minimax 函数基本上是相同的;我正在尝试在 C++ 中实现这一点,这就是我到目前为止所想到的:
double miniMax(Board eval, int iterations)
{
//I evaluate the board from both players' point of view and subtract the difference
if(iterations == 0)
return boardEval(eval, playerNumber) - boardEval(eval, opponentSide());
/*Here, playerTurn tells the findPossibleMoves function whose turn it is;
I mean, how do you generate a list of possible moves if you don't even know
whose turn it's supposed to be? But the problem is, I don't see where I can
get playerTurn from, as there are only 2 parameters in all the examples of
minimax I've seen*/
vector<int> moves = eval.findPossibleMoves(playerTurn);
//I'm assuming -∞ in the wikipedia article means a very low number?
int result = -999999999;
//Now I run this loop to evaluate each possible move
/*Also, the Lua example in the wiki article has
alpha = node.player==1 and math.max(alpha,score) or math.min(alpha,score)
Is alpha a boolean there?!*/
for(int i = 0; i * 2 < moves.size(); i++)
{
//I make a copy of the board...
Board temp = eval;
/*and make the next possible move... once again playerTurn crops up, and I
don't know where I can get that variable from*/
temp.putPiece(moves[i * 2], moves[i * 2 + 1], playerTurn);
/*So do I create a function max that returns the bigger of two doubles?*/
result = max(result, -miniMax(temp, iterations - 1));
}
return result;
/*So now I've returned the maximum score from all possible moves within a certain
# of moves; so how do I know which move to make? I have the score; how do I know
which sequence of moves that score belongs to?*/
}
如您所见,我对这个极小极大函数感到非常困惑。请至少给我一些提示来帮助我解决这个问题。
谢谢! :)
I have searched Google and Stackoverflow for this question, but I still don't understand how a minimax function works.
I found the wikipedia entry has a pseudocode version of the function:
function integer minimax(node, depth)
if node is a terminal node or depth <= 0:
return the heuristic value of node
α = -∞
for child in node: # evaluation is identical for both players
α = max(α, -minimax(child, depth-1))
return α
Several other minimax functions I found with Google are basically the same thing; I'm trying to implement this in C++, and this is what I have come up with so far:
double miniMax(Board eval, int iterations)
{
//I evaluate the board from both players' point of view and subtract the difference
if(iterations == 0)
return boardEval(eval, playerNumber) - boardEval(eval, opponentSide());
/*Here, playerTurn tells the findPossibleMoves function whose turn it is;
I mean, how do you generate a list of possible moves if you don't even know
whose turn it's supposed to be? But the problem is, I don't see where I can
get playerTurn from, as there are only 2 parameters in all the examples of
minimax I've seen*/
vector<int> moves = eval.findPossibleMoves(playerTurn);
//I'm assuming -∞ in the wikipedia article means a very low number?
int result = -999999999;
//Now I run this loop to evaluate each possible move
/*Also, the Lua example in the wiki article has
alpha = node.player==1 and math.max(alpha,score) or math.min(alpha,score)
Is alpha a boolean there?!*/
for(int i = 0; i * 2 < moves.size(); i++)
{
//I make a copy of the board...
Board temp = eval;
/*and make the next possible move... once again playerTurn crops up, and I
don't know where I can get that variable from*/
temp.putPiece(moves[i * 2], moves[i * 2 + 1], playerTurn);
/*So do I create a function max that returns the bigger of two doubles?*/
result = max(result, -miniMax(temp, iterations - 1));
}
return result;
/*So now I've returned the maximum score from all possible moves within a certain
# of moves; so how do I know which move to make? I have the score; how do I know
which sequence of moves that score belongs to?*/
}
As you can see, I'm pretty confused about this minimax function. Please at the very least give me some hints to help me with this.
Thanks! :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
来自维基百科的示例正在执行 NegaMax
和 Alpha/Beta 修剪。直接命名可能会对您有所帮助:
基础是 MiniMax,字面上的实现将涉及 2 个轮流(相互递归)的方法,每侧 1 个。
懒惰的程序员将其转变为 NegaMax,这是一种策略性放置
-
运算符的方法。Alpha/Beta 修剪正在跟踪最佳移动窗口(多个深度)以检测死分支。
您的
playerTurn
用于确定轮到谁了。在 NegaMax 中,您可以从深度(迭代)为奇数或偶数得出这一点。但使用 2 个参数(myColor、otherColor)并在每个级别切换它们会更容易。That sample from Wikipedia is doing NegaMax
with Alpha/Beta pruning.You may be helped by getting the naming straight:
The basis is MiniMax, a literal implementation would involve 2 methods that take turns (mutually recursive), 1 for each side.
Lazy programmers turn this into NegaMax, one method with a strategically placed
-
operator.Alpha/Beta pruning is keeping track of a Window of best moves (over multiple depths) to detect dead branches.
Your
playerTurn
is used to determine whose turn it is . In NegaMax you can derive this from the depth (iterations) being odd or even. But it would be easier to use 2 parameters (myColor, otherColor) and switch them at each level.你的 miniMax() 函数应该记住迄今为止找到的最佳移动。 ,而不是这段代码
因此,您应该这样做
:当然,您需要一个变量“bestMove”以及一种将找到的最佳移动返回给调用者的方法。
Your miniMax() function should remember the best move it found so far. So instead of this code:
You should do something like this:
Of course, you need a variable "bestMove" and a way to return the best move found to the caller.
将
playerTurn
变量添加为miniMax
的参数,并递归调用当前玩家最初移动的miniMax
。此外,
opponentSide
需要是playerTurn
的函数。Add the
playerTurn
variable as an argument tominiMax
, and callminiMax
which the current player's move initially and recursively.Also,
opponentSide
needs to be a function ofplayerTurn
.国际象棋编程 wiki 是开始博弈树搜索的好地方。对于您关于此举的问题:我认为最常见的是有两个最大功能。两个 max 函数之间的区别在于,一个仅返回分数,另一个返回分数和最佳移动。递归调用顺序如下所示:
有一些很好的论文,其中包含 Alpha Beta 算法的伪代码:
对于评论中的问题:和 math.max(alpha,score) 或 math.min(alpha,score) alpha 是布尔值吗?!
没有 alpha 是 alpha beta 算法中绑定的窗口。 alpha 值将更新为新值。因为 alpha 和 beta 在 negamax-Function 的递归调用中交换,所以 alpha 变量在下一个递归调用中引用 beta 变量。
对playerTurn 变量的一点注释:极小极大或α-β 算法不需要此信息。因此,我会将信息(下一个是谁)提供给董事会结构。函数 findPossibleMoves 和 boardEval 从 Board-Structure 获取所需的所有信息。
关于递归中断条件的一个注释:如果我正确理解你的代码,那么你只有带有
iterations == o
的代码。我认为这意味着算法已经达到了期望的深度。但是,如果在算法达到这个深度之前没有可能的移动,该怎么办?也许你应该写以下内容:A good place to start with game tree searching is the chess programming wiki. For your question about the move: I think it is most common to have two max-functions. The difference between the two max functions is that one returns only the score and the other returns the score and the best move. A recursive call order would be like following:
There are some good papers with pseudocode for the Alpha Beta algorithm:
To your question in the comment: and math.max(alpha,score) or math.min(alpha,score) Is alpha a boolean there?!
No alpha is a window bound in a alpha beta algorithm. The alpha value gets updated with a new value. Because alpha and beta are swapped with the recursive call of the negamax-Function the alpha variable refers to the beta variable in the next recursive call.
One note to the playerTurn variable: The minimax or alpha-beta algorithm doesn't need this information. So i would give the information -- who's next --, into the Board-Structure. The functions findPossibleMoves and boardEval get all information they need from the Board-Structure.
One note to the recursive break condition: If i understand your code right, then you only have the one with
iterations == o
. I think this means the algorithm has reached the desired depth. But what if there are no possible moves left befor the algorithm reaches this depth. Maybe you should write following:在您的伪代码中,节点变量必须包含有关当前板位置(或其他)的所有信息。该信息将包括轮到谁移动。
In your pseudocode, the node variable has to contain all the information about the current board position (or whatever). This information would include whose turn it is to move.