游戏通常需要玩家或团队在开始前制定策略,并根据游戏中的实际情况调整或建立新策略。对于计算机游戏而言,搜索算法是决定游戏策略的关键。
搜索算法的作用
如何工作
搜索算法的目标是找到最优的一系列行动步骤,以便达到最终目标并赢得游戏。这些算法利用特定游戏的胜利条件来寻找最佳行动方案。
将一个计算机游戏视作一棵树。树的节点代表未来的状态。搜索算法在这样的树中搜索以在每一步做出决策。
组合搜索
使用搜索算法的主要缺点在于它们本质上是穷举式的,会探索整个搜索空间,这可能会导致资源浪费。组合搜索通过使用启发式方法减少搜索空间,从而节省资源。
启发式搜索算法示例
-
极小极大算法(Minimax Algorithm) 极小极大算法是一种利用启发式方法加速搜索策略的方法。这种策略可以理解为两名玩家游戏中,每个玩家都试图预测对手的下一步,并试图最小化对手的效用函数,同时最大化自己的效用函数。
-
Alpha-Beta剪枝 Alpha-Beta剪枝算法的主要目的是避免搜索那些没有解决方案的部分。它通过设置两个界限——Alpha(最大下界)和Beta(最小上界),来限制可能解集的范围。这样可以将搜索引导到包含解决方案的部分,并忽略其余部分。
-
负极大算法(Negamax Algorithm) 负极大算法并不是与极小极大算法完全不同,但它具有更优雅的实现。主要优点在于只需要定义一个启发式函数,而不是像极小极大算法那样需要定义两个。
构建游戏机器人
对于构建用于玩两人游戏的人工智能机器人,可以使用easyAI
库。以下是构建两个具体游戏机器人的例子。
创建“最后一枚硬币”游戏的机器人
from easyAI import TwoPlayersGame, id_solve, Human_Player, AI_Player
from easyAI.AI import TT
class LastCoin_game(TwoPlayersGame):
def __init__(self, players):
self.players = players
self.nplayer = 1
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(self):
return self.num_coins <= 0
def is_over(self):
return self.win()
def score(self):
return 100 if self.win() else 0
def show(self):
print(f'{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()
创建“井字游戏”(Tic Tac Toe)的机器人
from easyAI import TwoPlayersGame, AI_Player, Negamax
from easyAI.Player import Human_Player
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 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.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.lose() else 0
if __name__ == "__main__":
algo = Negamax(7)
TicTacToe_game([Human_Player(), AI_Player(algo)]).play()