首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >国际象棋AI MiniMax算法不工作

国际象棋AI MiniMax算法不工作
EN

Stack Overflow用户
提问于 2018-03-15 06:50:41
回答 1查看 863关注 0票数 0

我已经在我的国际象棋AI中实现了minimax算法,我知道它不能正常工作,因为它只是来回移动1个棋子。

getPieces(true)返回当前电路板状态下的所有白色部分

getPieces(false)返回当前板子状态下的所有黑块

ChessPiece.getAllPotentialMoves()非常不言自明,可以获取特定片段的所有可能动作

PieceMovements.move()将一块(P)移动到适当的位置(m ->表示移动)

PieceMovements.undo()撤消上一次移动

searchDepth是第一次调用miniMax时首先作为深度值传递的变量,换句话说,它是您想要向下搜索的深度。原因是...

代码语言:javascript
复制
if(depth == searchDepth) {
    piece = p;
    move = m;
}

..。就是记录下来,然后移动去制作。我将这个值记录在搜索树的顶层。块和移动表示实际的块,并且移动算法认为是最有效的。

当调用miniMax时,它看起来像这样: miniMax(searchDepth,false)。错误,因为人工智能,黑色,是最小的。

下面是我的方法

代码语言:javascript
复制
public int miniMax(int depth, boolean maxi) {

    if(maxi) {
        if(depth == 0) return evaluateBoard();
        int max = -9999; //negative infinity
        for(ChessPiece p : getPieces(maxi)) for(Vector2 m : p.getAllPotentialMoves()) {
                PieceMovements.move(board, p, (int)m.x, (int)m.y);
                max = Math.max(max, miniMax(depth-1, !maxi));
                PieceMovements.undo();
                if(depth == searchDepth) {
                    piece = p;
                    move = m;
                }
            }
        return max;
    } else {
        if(depth == 0) return -evaluateBoard();
        int min = 9999; //positive infinity
        for(ChessPiece p : getPieces(maxi)) for(Vector2 m : p.getAllPotentialMoves()) {
                PieceMovements.move(board, p, (int)m.x, (int)m.y);
                min = Math.min(min, miniMax(depth-1, !maxi));
                PieceMovements.undo();
                if(depth == searchDepth) {
                    piece = p;
                    move = m;
                }
            }
        return min;
    }
}

和我的评估函数,它现在只取每一块的相对块价值,并将它们相加:

代码语言:javascript
复制
public int evaluateBoard() {
    int total = 0;
    for(ChessPiece[] row : board)
        for(ChessPiece piece : row)
            if(piece != null)
                switch(piece.getPiece()) {
                    case WPAWN:
                    case BPAWN:
                        total += RelativePieceValues.PAWN;
                        //a pawn about to be promoted takes on more value
                        if(piece.getPosition().y == 1 || piece.getPosition().y == 6)
                            total += 50; //50 + 10 = 60
                        break;
                    case WKNIGHT:
                    case BKNIGHT:
                        total += RelativePieceValues.KNIGHT;
                        break;
                    case WBISHOP:
                    case BBISHOP:
                        total += RelativePieceValues.BISHOP;
                        break;
                    case WROOK:
                    case BROOK:
                        total += RelativePieceValues.ROOK;
                        break;
                    case WQUEEN:
                    case BQUEEN:
                        total += RelativePieceValues.QUEEN;
                        break;
                    case WKING:
                    case BKING:
                        total += RelativePieceValues.KING;
                        break;
                }

    return total;
}

和RelativePieceValues类:

代码语言:javascript
复制
public class RelativePieceValues{

//piece value constants
public static final int PAWN = 10;
public static final int KNIGHT = 30;
public static final int BISHOP = 30;
public static final int ROOK = 50;
public static final int QUEEN = 90;
public static final int KING = 900;
}

如果你有任何问题,请提出来。感谢您的回复,我已经被困在这个问题上有一段时间了。我想知道是不是我的最小最大算法或者我的评估函数真的出了问题,或者我的程序中可能有其他你看不到的错误。谢谢。

EN

回答 1

Stack Overflow用户

发布于 2020-01-08 20:59:45

正如答案中指出的,您没有使用minimax函数的结果。下面是我用Python开发的工作版本,希望你能把它翻译成java :)

这一个是使用alpha-beta剪枝来提高性能。

使用极大极小函数的初始调用:

代码语言:javascript
复制
best_move, evaluation = minimax(board, 5, -math.inf, math.inf, True)

Minimax函数本身。在board类中使用board.is_human_turn来确定玩家是谁。然后我们得到该玩家(该位置的子代)的所有可能的动作。

然后它检查我们是否达到了最大深度,或者游戏是否在该位置结束(绘制或检查配对)。

对于每个玩家(分别是最大化和最小化),它会遍历所有的子对象。它复制一个棋盘(不改变原始板),并在棋盘上移动(其中一个子棋盘)。然后,它计算所有节点中的评估,并返回最佳移动和评估。

代码语言:javascript
复制
def minimax(board, depth, alpha, beta, maximizing_player):

    board.is_human_turn = not maximizing_player
    children = board.get_all_possible_moves()

    if depth == 0 or board.is_draw or board.is_check_mate:
        return None, evaluate(board)

    best_move = random.choice(children)

    if maximizing_player:
        max_eval = -math.inf
        for child in children:
            board_copy = copy.deepcopy(board)
            board_copy.move(child)
            current_eval = minimax(board_copy, depth - 1, alpha, beta, False)[1]
            if current_eval > max_eval:
                max_eval = current_eval
                best_move = child
            alpha = max(alpha, current_eval)
            if beta <= alpha:
                break
        return best_move, max_eval

    else:
        min_eval = math.inf
        for child in children:
            board_copy = copy.deepcopy(board)
            board_copy.move(child)
            current_eval = minimax(board_copy, depth - 1, alpha, beta, True)[1]
            if current_eval < min_eval:
                min_eval = current_eval
                best_move = child
            beta = min(beta, current_eval)
            if beta <= alpha:
                break
        return best_move, min_eval

我的评估函数目前非常简单,只考虑棋子的价值以及它们在棋盘上的位置。例如,一个骑士最初的价值是320,然后根据它的位置进行加法或减法。有关更多信息,请参阅此链接:https://www.chessprogramming.org/Simplified_Evaluation_Function

你还可以实现一本开场白,这样你就可以在每一场比赛中有一个良好的开端,而不必花费时间计算位置。

希望这能有所帮助!

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49288874

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档