賭勝負


遊戲(賭勝負)採用策略進行。 每個球員或球隊在開始比賽前都會制定一個戰略,他們必須根據目前的比賽情況改變或制定新的戰略。

搜尋演算法

考慮電腦遊戲也採用與上述相同的策略。 請注意,搜尋演算法是計算電腦遊戲策略的演算法。

怎麼執行的
搜尋演算法的目標是找到最優的一組移動,以便他們可以到達最終目的地並獲勝。 這些演算法使用勝出的一組條件,每場比賽都有所不同,以找到最佳的移動方式。

將電腦遊戲形象化為樹。 我們都知道樹有節點。 從根開始,可以進入最終的獲勝節點,但是具有最佳的移動路徑。 這是搜尋演算法的工作。 這種樹中的每個節點代表未來的狀態。 搜尋演算法搜尋這棵樹,在遊戲的每個步驟或節點做出決定。

組合搜尋

使用搜尋演算法的主要缺點是它們本質上是窮盡的,這就是為什麼他們探索整個搜尋空間以找到導致資源浪費的解決方案。如果這些演算法需要搜尋整個搜尋空間以找到最終解決方案,那將更加麻煩。

要消除這樣的問題,可以使用組合搜尋,它使用啟發式來探索搜尋空間,並通過消除可能的錯誤動作來減小其大小。 因此,這樣的演算法可以節省資源。 這裡討論了一些使用啟發式搜尋空間並節省資源的演算法 -

Minimax演算法

這是組合搜尋使用啟發式策略加快搜尋策略的策略。 Minimax策略的概念可以通過兩個玩家遊戲的例子來理解,其中每個玩家都試圖預測對手的下一步行動並嘗試最小化該功能。 而且,為了獲勝,玩家總是會根據當前的情況嘗試最大化自己的功能。

啟發式在像Minimax這樣的策略中扮演著重要的角色。 樹的每個節點都會有一個與之相關的啟發式函式。 基於這種啟發式方法,它將決定向最有利於他們的節點邁進。

Alpha-Beta修剪

Minimax演算法的一個主要問題是它可以探索那些無關的樹的部分,導致資源的浪費。 因此,必須有一個策略來決定樹的哪一部分是相關的,哪一個是無關緊要的,並且將不相關的部分留給未開發的部分。 Alpha-Beta修剪就是這樣一種策略。

Alpha-Beta修剪演算法的主要目標是避免搜尋樹中沒有任何解決方案的那些部分。 Alpha-Beta修剪的主要概念是使用名為Alpha的兩個邊界(最大下界)和Beta,即最小上界。 這兩個引數是限制可能解決方案集合的值。 它將當前節點的值與alpha和beta引數的值進行比較,以便它可以移動到具有解決方案的樹部分並丟棄其餘部分。

Negamax演算法

這個演算法與Minimax演算法沒有區別,但它具有更優雅的實現。 使用Minimax演算法的主要缺點是需要定義兩個不同的啟發式函式。 這些啟發式之間的聯絡是,對於一個玩家來說遊戲的狀態越好,對另一個玩家來說就越糟糕。 在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

機器人玩井字遊戲

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 .