[英]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.