Artificial Intelligence With Python 简明教程

AI with Python – Gaming

游戏通过策略进行。在开始游戏之前,每位玩家或团队都会制定策略,并且他们必须根据游戏中的当前情况更改或构建新策略。

Search Algorithms

您还必须使用与上述相同的策略考虑计算机游戏。请注意,搜索算法是确定计算机游戏策略的算法。

How it works

搜索算法的目标是找到最佳的移动集合,以便他们能够到达最终目的地并获胜。这些算法使用因游戏而异的获胜条件集合来找到最佳移动。

将计算机游戏可视化为一棵树。我们知道树具有节点。从根部开始,我们可以到达最终获胜节点,但采用最佳的移动。那是搜索算法的工作。此类树中的每个节点都代表一个未来状态。搜索算法通过此树搜索,并在游戏的每个步骤或节点做出决策。

使用搜索算法的主要缺点是它们本质上是详尽无遗的,这就是为什么它们探索整个搜索空间以找到导致浪费资源的解决方案的原因。如果这些算法需要搜索整个搜索空间以找到最终解决方案,那将更加麻烦。

为了消除此类问题,我们可以使用组合搜索,它利用启发式探索搜索空间,并通过消除可能的错误走法来缩小搜索空间。因此,此类算法可以节省资源。此处讨论了使用启发式探索空间并节省资源的一些算法。

Minimax Algorithm

这是组合搜索使用的策略,它利用启发式来加速搜索策略。极小化最大化策略的概念可以用双人游戏为例来理解,在双人游戏中,每个玩家尝试预测对手的下一步走法并尝试最小化该函数。此外,为了获胜,玩家始终尝试根据当前情况最大化其自己的函数。

启发式在极小化最大化之类的策略中扮演着重要角色。树的每个节点都会有一个与其关联的启发式函数。根据启发式,它将做出决定,向对他们最有利的节点移动。

Alpha-Beta Pruning

极小化最大化算法的一个主要问题是它可以探索树中那些与问题无关的部分,从而导致资源浪费。因此,必须有一个策略来决定树的哪些部分是相关的,哪些部分是不相关的,并让不相关的部分未被探索。Alpha-Beta 剪枝就是这样一种策略。

Alpha-Beta 剪枝算法的主要目标是避免搜索树中那些没有任何解决方案的部分。Alpha-Beta 剪枝的主要概念是使用两个边界,名为 Alpha ,最大下限,和 Beta ,最小上限。这两个参数是限制一组可能解决方案的值。它将当前节点的值与 alpha 值和 beta 值进行比较,以便它可以移动到具有解决方案的树部分并丢弃其余部分。

Negamax Algorithm

此算法与极小化最大化算法没有区别,但它具有更优雅的实现。使用极小化最大化算法的主要缺点是,我们需要定义两个不同的启发式函数。这些启发式之间的联系是,游戏中的一个状态对一个玩家越好,对另一个玩家就越糟。在 Negamax 算法中,两个启发式函数的相同工作是在单个启发式函数的帮助下完成的。

Building Bots to Play Games

对于在 AI 中构建机器人来玩双人游戏,我们需要安装 easyAI 库。它是一个人工智能框架,提供构建双人游戏的所有功能。你可以使用以下命令下载它:

pip install easyAI

A Bot to Play Last Coin Standing

在这个游戏中,一堆硬币。每个玩家都必须从这堆硬币中取出一定数量的硬币。游戏的目标是避免拿走堆中最后一个硬币。我们将使用 LastCoinStanding 类,该类继承自 easyAI 库中的 TwoPlayersGame 类。以下代码显示了此游戏的 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

A Bot to Play Tic Tac Toe

井字棋非常熟悉,是其中最受欢迎的游戏之一。让我们通过在 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

为提高人工智能,定义何时玩家移动 -

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 .