- Python AI 教程
- 首页
- Python AI – 基础概念
- Python AI – 入门指南
- Python AI – 机器学习
- Python AI – 数据准备
- 监督学习:分类
- 监督学习:回归
- Python AI – 逻辑编程
- 无监督学习:聚类
- 自然语言处理
- Python AI – NLTK 包
- 分析时间序列数据
- Python AI – 语音识别
- Python AI – 启发式搜索
- Python AI – 游戏
- Python AI – 神经网络
- 强化学习
- Python AI – 遗传算法
- Python AI – 计算机视觉
- Python AI – 深度学习
- Python AI 资源
- Python AI – 快速指南
- Python AI – 有用资源
- Python AI – 讨论
Python AI – 游戏
游戏都是以策略进行的。每个玩家或团队在开始游戏之前都会制定策略,并且他们必须根据游戏中的当前情况改变或制定新的策略。
搜索算法
您也需要像上面一样,将电脑游戏视为同样的策略。请注意,搜索算法是找出电脑游戏中策略的算法。
工作原理
搜索算法的目标是找到最佳的一系列移动,以便它们能够到达最终目的地并获胜。这些算法使用每个游戏都不一样的获胜条件集来找到最佳移动。
将电脑游戏可视化为树。我们知道树有节点。从根开始,我们可以到达最终的获胜节点,但需要使用最佳的移动。这就是搜索算法的工作。此类树中的每个节点都代表一个未来状态。搜索算法搜索这棵树,以便在游戏的每个步骤或节点做出决策。
组合搜索
使用搜索算法的主要缺点是它们本质上是穷举的,这就是为什么它们会探索整个搜索空间以找到解决方案,从而导致资源浪费。如果这些算法需要搜索整个搜索空间以找到最终解决方案,则会更加麻烦。
为了消除此类问题,我们可以使用组合搜索,它使用启发式方法来探索搜索空间,并通过消除可能的错误移动来减小搜索空间的大小。因此,此类算法可以节省资源。这里讨论了一些使用启发式方法搜索空间并节省资源的算法:
极大极小算法
这是组合搜索使用的策略,它使用启发式方法来加速搜索策略。可以通过双人游戏的例子来理解极大极小策略的概念,在双人游戏中,每个玩家都试图预测对手的下一步行动并试图最小化该函数。此外,为了获胜,玩家总是试图根据当前情况最大化自己的函数。
启发式方法在这种策略(例如极大极小算法)中起着重要作用。树的每个节点都将与一个启发式函数相关联。根据该启发式方法,它将做出决策,朝着最有利于它们的节点移动。
Alpha-Beta 剪枝
极大极小算法的一个主要问题是它可以探索与之无关的树的部分,从而导致资源浪费。因此,必须有一种策略来确定树的哪一部分是相关的,哪一部分是不相关的,并使不相关的部分未被探索。Alpha-Beta 剪枝就是这样一种策略。
Alpha-Beta 剪枝算法的主要目标是避免搜索那些没有任何解决方案的树的部分。Alpha-Beta 剪枝的主要概念是使用两个边界,名为Alpha(最大下界)和Beta(最小上界)。这两个参数是限制可能解决方案集的值。它将当前节点的值与 alpha 和 beta 参数的值进行比较,以便它可以移动到具有解决方案的树的部分并丢弃其余部分。
Negamax 算法
此算法与极大极小算法没有区别,但它具有更优雅的实现。使用极大极小算法的主要缺点是我们需要定义两个不同的启发式函数。这些启发式方法之间的联系是,游戏的一个状态对一个玩家越有利,对另一个玩家就越不利。在 Negamax 算法中,两个启发式函数的工作由单个启发式函数完成。
构建机器人来玩游戏
为了在 AI 中构建机器人来玩双人游戏,我们需要安装easyAI 库。这是一个人工智能框架,提供构建双人游戏的所有功能。您可以使用以下命令下载它:
pip install easyAI
一个玩“最后一个硬币”的机器人
在这个游戏中,将有一堆硬币。每个玩家都必须从那堆硬币中取走一定数量的硬币。游戏的目标是避免取走堆中最后一个硬币。我们将使用从easyAI 库的TwoPlayersGame 类继承的LastCoinStanding 类。以下代码显示了此游戏的 Python 代码:
导入所需的包,如下所示:
from easyAI import TwoPlayersGame, id_solve, Human_Player, AI_Player from easyAI.AI import TT
现在,从TwoPlayerGame 类继承类以处理游戏的所有操作:
class LastCoin_game(TwoPlayersGame): def __init__(self, players):
现在,定义玩家和将要开始游戏的玩家。
self.players = players self.nplayer = 1
现在,定义游戏中硬币的数量,这里我们使用 15 个硬币进行游戏。
self.num_coins = 15
定义玩家在一次移动中可以取走的最大硬币数量。
self.max_coins = 4
现在,需要定义一些特定内容,如下面的代码所示。定义可能的移动。
def possible_moves(self): return [str(a) for a in range(1, self.max_coins + 1)]
定义硬币的移除
def make_move(self, move): self.num_coins -= int(move)
定义谁取走了最后一个硬币。
def win_game(self): return self.num_coins <= 0
定义何时停止游戏,即有人获胜时。
def is_over(self): return self.win()
定义如何计算分数。
def score(self): return 100 if self.win_game() else 0
定义堆中剩余的硬币数量。
def show(self): print(self.num_coins, 'coins left in the pile') if __name__ == "__main__": tt = TT() LastCoin_game.ttentry = lambda self: self.num_coins
使用以下代码块解决游戏:
r, d, m = id_solve(LastCoin_game, range(2, 20), win_score=100, tt=tt) print(r, d, m)
决定谁将开始游戏
game = LastCoin_game([AI_Player(tt), Human_Player()]) game.play()
您可以找到以下输出以及此游戏的简单玩法:
d:2, a:0, m:1 d:3, a:0, m:1 d:4, a:0, m:1 d:5, a:0, m:1 d:6, a:100, m:4 1 6 4 15 coins left in the pile Move #1: player 1 plays 4 : 11 coins left in the pile Player 2 what do you play ? 2 Move #2: player 2 plays 2 : 9 coins left in the pile Move #3: player 1 plays 3 : 6 coins left in the pile Player 2 what do you play ? 1 Move #4: player 2 plays 1 : 5 coins left in the pile Move #5: player 1 plays 4 : 1 coins left in the pile Player 2 what do you play ? 1 Move #6: player 2 plays 1 : 0 coins left in the pile
一个玩井字棋的机器人
井字棋非常熟悉,也是最受欢迎的游戏之一。让我们使用 Python 中的easyAI 库创建此游戏。以下代码是此游戏的 Python 代码:
导入包,如下所示:
from easyAI import TwoPlayersGame, AI_Player, Negamax from easyAI.Player import Human_Player
从TwoPlayerGame 类继承类以处理游戏的所有操作:
class TicTacToe_game(TwoPlayersGame): def __init__(self, players):
现在,定义玩家和将要开始游戏的玩家:
self.players = players self.nplayer = 1
定义棋盘的类型:
self.board = [0] * 9
现在,需要定义一些特定内容,如下所示:
定义可能的移动
def possible_moves(self): return [x + 1 for x, y in enumerate(self.board) if y == 0]
定义玩家的移动:
def make_move(self, move): self.board[int(move) - 1] = self.nplayer
为了增强 AI,定义玩家何时进行移动:
def umake_move(self, move): self.board[int(move) - 1] = 0
定义对手三子连成的失败条件
def condition_for_lose(self):
possible_combinations = [[1,2,3], [4,5,6], [7,8,9],
[1,4,7], [2,5,8], [3,6,9], [1,5,9], [3,5,7]]
return any([all([(self.board[z-1] == self.nopponent)
for z in combination]) for combination in possible_combinations])
定义检查游戏结束的条件
def is_over(self): return (self.possible_moves() == []) or self.condition_for_lose()
显示游戏中玩家的当前位置
def show(self):
print('\n'+'\n'.join([' '.join([['.', 'O', 'X'][self.board[3*j + i]]
for i in range(3)]) for j in range(3)]))
计算分数。
def scoring(self): return -100 if self.condition_for_lose() else 0
定义主方法以定义算法并开始游戏:
if __name__ == "__main__": algo = Negamax(7) TicTacToe_game([Human_Player(), AI_Player(algo)]).play()
您可以看到以下输出以及此游戏的简单玩法:
. . . . . . . . . Player 1 what do you play ? 1 Move #1: player 1 plays 1 : O . . . . . . . . Move #2: player 2 plays 5 : O . . . X . 121 . . . Player 1 what do you play ? 3 Move #3: player 1 plays 3 : O . O . X . . . . Move #4: player 2 plays 2 : O X O . X . . . . Player 1 what do you play ? 4 Move #5: player 1 plays 4 : O X O O X . . . . Move #6: player 2 plays 8 : O X O O X . . X .