我使用维基百科的伪代码作为参考 –
function alphabeta(node, depth, α, β, Player) if depth = 0 or node is a terminal node return the heuristic value of node if Player = MaxPlayer for each child of node α := max(α, alphabeta(child, depth-1, α, β, not(Player) )) if β ≤ α break (* Beta cut-off *) return α else for each child of node β := min(β, alphabeta(child, depth-1, α, β, not(Player) )) if β ≤ α break (* Alpha cut-off *) return β
这是我的Java实现 –
private int alphabeta(Node newNode, int depth, int alpha, int beta, boolean Player) { Integer[] children; if(depth == 0 || newNode.allNodesFull()){ return (newNode.blacknodes() - newNode.whitenodes()); } if(Player == false){ children = newNode.findMovesBlack(); Arrays.sort(children); for(Integer child: children){ nodesGenerated ++; alpha = Math.max(alpha, alphabeta(new Node(newNode.move(child), true), depth - 1, alpha, beta, !Player)); if(beta <= alpha) break; }return alpha; }else{ children = newNode.findMovesWhite(); Arrays.sort(children); for(Integer child: children){ nodesGenerated ++; beta = Math.min(beta, alphabeta(new Node(newNode.move(child), false), depth - 1, alpha, beta, !Player)); if(beta <= alpha) break; }return beta; }}
经过几次修改后,我的代码不再有提前返回的问题,但现在的问题是alpha和beta值从未改变过
我将解释一下发生的情况,假设它们是有效的
findMovesBlack()和findMovesWhite()都返回Integer[]数组,包含了任一玩家可以移动的所有可能位置,无论轮到谁移动。对于Reversi的初始位置,findMovesBlack()会返回[19, 26, 37, 44]
allNodesFull()返回一个布尔值,如果findMovesBlack()和findMovesWhite()的长度都为0,则为true。
blacknodes()和whitenodes()分别返回黑子或白子的数量。
Node.move(int coordinate)返回一个String[]数组,其中包含已翻转并放置的新位置。相信我,它工作得很好。
Node(String[] gameboard, boolean player-to-move)只是根据我们找到的参数设置一个新位置。
我认为这就是你需要看到的所有内容。我已经解决了后端的所有问题。
回答:
答案在于beta和alpha值的实现。我不得不对等于号的位置做了很多调整。