极小化极大算法与跳棋游戏

我正在使用极小化极大算法和Python实现跳棋游戏。游戏中有两个玩家 – 都是电脑。我一直在寻找类似问题的解决方案,但没有找到任何结果,并且已经为此挣扎了几天。我的入口点是这个函数:

def run_game(board):    players = board.players    is_move_possible = True    move = 0    while is_move_possible:        is_move_possible = move_piece_minimax(board, players[move % 2])        move += 1

它启动游戏并调用下一个函数,该函数应该根据极小化极大算法为第一位玩家做出最佳移动。在第一次移动之后,它会为第二位玩家调用这个函数,这个循环将在其中一位玩家赢得游戏后结束。该函数如下所示:

def move_piece_minimax(board, player):    best_move = minimax(copy.deepcopy(board), player, 0)    if best_move.score == +infinity or best_move.score == -infinity:        return False    move_single_piece(board.fields, player, best_move)    return True

第一行调用极小化极大算法,我将在后面描述,它应该为玩家找到最佳可能的移动。我在这里传递了整个棋盘的深拷贝,因为我不想在执行极小化极大算法时编辑原始棋盘。条件检查获胜条件,因此如果最大化玩家或最小化玩家获胜。如果没有一方获胜,则执行best_move。现在回到主要问题,我实现了极小化极大算法如下:

def minimax(board, player, depth):    best_move = Move(-1, -1, -infinity if player.name == PLAYER_NAMES['P1'] else +infinity)    if depth == MAX_SEARCH_DEPTH or game_over(board):        score = evaluate(board)        return Move(-1, -1, score)    for correct_move in get_all_correct_moves(player, board.fields):        x, y, piece = correct_move.x, correct_move.y, correct_move.piece        move_single_piece(board.fields, player, correct_move)        player_to_move = get_player_to_move(board, player)        move = minimax(board, player_to_move, depth + 1)    # <--- 这里是递归        move.x = x        move.y = y        move.piece = piece        if player.name == PLAYER_NAMES['P1']:            if move.score > best_move.score:                best_move = move  # 最大值        else:            if move.score < best_move.score:                best_move = move  # 最小值    return best_move

我决定玩家‘P1’最大化玩家,玩家‘P2’最小化玩家。从第一行开始,best_move变量保存对Move对象的引用,该对象具有以下字段:

class Move:    def __init__(self, x, y, score, piece=None):        self.x = x        self.y = y        self.score = score        self.piece = piece

我将best_move.score初始化为最大化玩家的-Infinity,对于其他情况则为+Infinity。

第一个条件检查深度是否达到了最大级别(为了测试目的,设置为2)或游戏是否结束。如果是,则评估当前棋盘的情况并返回一个包含当前棋盘得分的Move对象。否则,我的算法会寻找该玩家所有合法/正确的移动,并执行第一个移动。

执行后,该函数以递归方式调用,但深度增加并更换移动的玩家。该函数在更改参数后再次运行,直到第一个if条件执行。

一旦执行进入该分支,将返回棋盘的评估得分,之后,在递归调用后的for循环中,将移动的坐标x、y和棋子分配给Move对象。

最后的条件检查新得分是否是该特定玩家的更好得分。如果这是最大化玩家,在我的例子中是P1,它会检查新得分是否高于之前的得分。对于最小化玩家,算法寻找最低得分。

在为该玩家执行所有正确移动后,我的算法应该返回一个best_move。

预期结果
Move类的单个对象,包含坐标x和y,评估的棋盘得分,仅在其中一位玩家获胜的情况下为+Infinity/-Infinity,以及将移动到[x, y]坐标的Piece类对象。

实际结果
Move类的单个对象,包含坐标x和y,评估的棋盘得分在第一次调用极小化极大函数后等于+Infinity。没有棋子改变其位置,因此游戏尚未结束。然而,得分为+Infinity,因此函数move_piece_minimax()将返回False – 意味着没有更多可能的移动。因此,我的程序将在棋盘上没有任何变化的情况下停止执行。这是初始和最终棋盘状态的截图 – 在执行过程中没有任何变化,因为第一次调用返回了+Infinity。

初始和最终棋盘状态

我的问题是,在实现极小化极大算法时我遗漏了什么?我犯了什么错误?我也欢迎任何代码改进或建议。如果您需要了解我的实现的任何其他函数,我会提供它们。谢谢!


回答:

在极小化极大函数中,您应该执行以下操作之一

1. 在放置棋子之前制作棋盘的副本

2. 在递归调用极小化极大函数后移除放置的棋子

否则,您的棋盘将在递归过程中被棋子填满,您将收到一个错误,指出没有剩余的移动。极小化极大算法旨在通过放置棋子进行深入搜索,因此您应该实现一种方法,使其不修改原始棋盘。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注