繁体   English   中英

Python3中的Minimax算法实现

[英]Minimax Algorithm Implementation In Python3

我一直在尝试用Python构建一个Tic-Tac-Toe机器人。 我试图避免使用Minimax算法,因为我非常想知道如何实现它。 到现在。 我(最终)编写了一种算法,该算法很容易陷入失败,并且很容易丢失,这有点违反了使计算机播放井字游戏的目的。 因此,我终于鼓起勇气尝试使用TRY来实现该算法。 我偶然发现了这个 StackOverflow帖子。 我尝试在此处实施所选的答案,但我听不懂大部分内容。 该答案中的代码如下:

def minimax(self, player, depth = 0) :
    if player == "o":
        best = -10
    else:
        best = 10
    if self.complete():
        if self.getWinner() == "x": # 'X' is the computer
            return -10 + depth, None
        elif self.getWinner() == "tie":
            return 0, None
        elif self.getWinner() == "o" : # 'O' is the human
            return 10 - depth, None
    for move in self.getAvailableMoves() :
        self.makeMove(move, player)
        val, _ = self.minimax(self.getEnemyPlayer(player), depth+1)
        print(val)

        self.makeMove(move, ".")

        if player == "o" :
            if val > best :
                best, bestMove = val, move
        else :
            if val < best :
                best, bestMove = val, move

    return best, bestMove

首先,为什么我们在计算机获胜时返回-10 + depth ,而在人类获胜时返回10 - depth (我知道为什么在平局时我们返回0)。 其次, depth参数在做什么? 有什么办法可以忽略吗? 我们应该省略吗?

我可能缺少有关该算法的一些基本知识,但是我我已经足够了解了。 请记住,我对递归算法非常陌生...

编辑

所以,现在我使自己成为函数:

def minimax(self, player):
    won = 10
    lost = -10
    draw = 0

    if self.has_won(HUMAN):
        return lost, None
    elif self.has_won(BOT):
        return won, None

    if not(self.board_is_empty()):
        return draw, None

    moves = self.get_available_moves()

    for move in moves:
        self.play_move(move[0], move[1], player)
        make_board(self.board)

        if self.board_is_empty():
            val, _ = self.minimax(self.get_enemy_player(player))
        self.rewind_move(move)

        if val==won:
            return val, move

但是现在的问题是,当移动以平局或亏损(对于计算机)结束时,我无法理解会发生什么。 我认为它正在做的是通过举棋的结果来查看SOMEONE是否获胜(这可能是发生的情况,因为我已经对其进行了测试),如果SOMEONE获胜,则返回该举棋。 如何修改此代码以使其正常工作?

注意:

  • 该函数在class ,因此是self关键字。

  • moves是一个包含元组的列表。 例如。 moves = [(0, 1), (2, 2)]等。因此,moves包含所有空白方块。 因此,每个moves[i][j]是一个整数模3。

  • 我正在使用Jacques de Hooge在下面的答案中建议的详尽算法。

首先请注意10-深度=-(-10 +深度)。 因此,计算机的胜利与人类的胜利有相反的迹象。 这样,可以将它们添加起来以评估游戏板状态的值。 虽然使用tictactoe并不是真正需要的,但在象棋这样的游戏中却是如此,因为尝试所有可能的组合直到将棋子都花了很长时间,因此必须以某种方式评估游戏板的状态,包括输赢件,每件都值一定数量的点数,根据经验得出的值)。

假设现在我们只看10深度(因此人类会获胜)。 最吸引人的胜利是需要最少打球(动作)的胜利。 由于每次移动或反向移动都会导致深度增加,所以更多的移动将导致参数深度变大,因此10深度(优势的“数量”)会变小。 因此,快速胜利胜于宽大的胜利。 10个就足够了,因为在3 x 3的运动场中总共只能进行9个动作。

简而言之:由于tictactoe非常简单,因此实际上可以在详尽的递归搜索中找到获胜组合。 但是minimax算法适用于象棋这样的更复杂的情况,在这种情况下,必须根据损失(负)和收益(正)之和来评估中间情况。

是否应省略depth参数? 如果您在乎最快的获胜:否。如果您仅在乎一个胜利(单身),那么它确实可以省略,因为可以进行详尽的搜索。

[编辑]

抽筋的意思是穷举,仅意味着搜索9层深,因为游戏永远不会持续太久。

使用参数播放器(o或x)和返回值得失进行递归函数,该值首先在最深的递归级别上确定,然后向上递归通过递归树。 让它使用所有免费字段的相反播放器作为参数进行调用。 如果有任何续集导致机器为每个级别的人员赢得了胜利,那么移动机器就是正确的选择。

注意:我所做的假设是存在获胜策略。 如果不是这种情况(可以联系),那么您拥有的算法可能是最佳选择。 我记得使用tictactoe的人总是可以按照上述方式赢得比赛。 因此,该算法将至少赢得所有游戏的50%。 对于非完美的人类玩家,如果计算机无法启动,如果人类玩家执行次优操作,那么它也可能会获胜,

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM