亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

使用python實現翻轉棋游戲的案例

發布時間:2021-04-06 12:56:19 來源:億速云 閱讀:285 作者:小新 欄目:開發技術

這篇文章將為大家詳細講解有關使用python實現翻轉棋游戲的案例,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

幾點改進說明:

  • 拆分成四個文件:board.py,player.py,ai.py,othello.py。使得整個結構更清晰,更通用,更易于維護。

  • AI 的水平跟 minimax 的遞歸深度,以及評價函數有關。基于此,我把 minimax 和評價函數都放到 AI 類里面

  • AIPlayer 使用了多重繼承。繼承了 Player 與 AI 兩個類

  • Game 類中把原run函數里的生成兩個玩家的部分提出來,寫成一個函數make_two_players,使得 run函數結構更清晰

  • AI 玩家等級不要選擇 0:beginer。會報錯,還沒調試好

board.py

'''
作者:hhh6460
時間:2017年7月1日
'''

class Board(object):
 def __init__(self):
  self.empty = '.'
  self._board = [[self.empty for _ in range(8)] for _ in range(8)] # 規格:8*8
  self._board[3][4], self._board[4][3] = 'X', 'X'
  self._board[3][3], self._board[4][4] = 'O', 'O'
  
 # 增加 Board[][] 索引語法
 def __getitem__(self, index):
  return self._board[index]
 
 # 打印棋盤
 def print_b(self):
  board = self._board
  print(' ', ' '.join(list('ABCDEFGH')))
  for i in range(8):
   print(str(i+1),' '.join(board[i]))
   
 # 棋局終止
 def teminate(self):
  list1 = list(self.get_legal_actions('X'))
  list2 = list(self.get_legal_actions('O'))
  return [False, True][len(list1) == 0 and len(list2) == 0]
  
 # 判斷贏家
 def get_winner(self):
  s1, s2 = 0, 0
  for i in range(8):
   for j in range(8):
    if self._board[i][j] == 'X':
     s1 += 1
    if self._board[i][j] == 'O':
     s2 += 1
  if s1 > s2:
   return 0 # 黑勝
  elif s1 < s2:
   return 1 # 白勝
  elif s1 == s2:
   return 2 # 平局
 # 落子
 def _move(self, action, color):
  x,y = action
  self._board[x][y] = color
  
  return self._flip(action, color)
  
 
  
 
 # 翻子(返回list)
 def _flip(self, action, color):
  flipped_pos = []
  
  for line in self._get_lines(action):
   for i,p in enumerate(line):
    if self._board[p[0]][p[1]] == self.empty: 
     break
    elif self._board[p[0]][p[1]] == color:
     flipped_pos.extend(line[:i])
     break
  
  for p in flipped_pos:
   self._board[p[0]][p[1]] = color
   
  return flipped_pos
  
 # 撤銷
 def _unmove(self, action, flipped_pos, color):
  self._board[action[0]][action[1]] = self.empty
  
  uncolor = ['X', 'O'][color=='X']
  for p in flipped_pos:
   self._board[p[0]][p[1]] = uncolor
   
 # 生成8個方向的下標數組,方便后續操作
 def _get_lines(self, action):
  '''說明:剛開始我是用一維棋盤來考慮的,后來改為二維棋盤。偷懶,不想推倒重來,簡單地修改了一下'''
  board_coord = [(i,j) for i in range(8) for j in range(8)] # 棋盤坐標
  
  r,c = action
  ix = r*8 + c
  r, c = ix//8, ix%8
  left = board_coord[r*8:ix] # 要反轉
  right = board_coord[ix+1:(r+1)*8]
  top = board_coord[c:ix:8] # 要反轉
  bottom = board_coord[ix+8:8*8:8]
  
  if r <= c:
   lefttop = board_coord[c-r:ix:9] # 要反轉
   rightbottom = board_coord[ix+9:(7-(c-r))*8+7+1:9]
  else:
   lefttop = board_coord[(r-c)*8:ix:9] # 要反轉
   rightbottom = board_coord[ix+9:7*8+(7-(c-r))+1:9]
  
  if r+c<=7:
   leftbottom = board_coord[ix+7:(r+c)*8:7]
   righttop = board_coord[r+c:ix:7] # 要反轉
  else:
   leftbottom = board_coord[ix+7:7*8+(r+c)-7+1:7]
   righttop = board_coord[((r+c)-7)*8+7:ix:7] # 要反轉
  
  # 有四個要反轉,方便判斷
  left.reverse()
  top.reverse()
  lefttop.reverse()
  righttop.reverse()
  lines = [left, top, lefttop, righttop, right, bottom, leftbottom, rightbottom]
  return lines
  
 # 檢測,位置是否有子可翻
 def _can_fliped(self, action, color):
  flipped_pos = []
  
  for line in self._get_lines(action):
   for i,p in enumerate(line):
    if self._board[p[0]][p[1]] == self.empty: 
     break
    elif self._board[p[0]][p[1]] == color:
     flipped_pos.extend(line[:i])
     break
  return [False, True][len(flipped_pos) > 0]
  
 # 合法走法
 def get_legal_actions(self, color):
  uncolor = ['X', 'O'][color=='X']
  uncolor_near_points = [] # 反色鄰近的空位
  
  board = self._board
  for i in range(8):
   for j in range(8):
    if board[i][j] == uncolor:
     for dx,dy in [(-1,0),(-1,1),(0,1),(1,1),(1,0),(1,-1),(0,-1)]:
      x, y = i+dx, j+dy
      if 0 <= x <=7 and 0 <= y <=7 and board[x][y] == self.empty and (x, y) not in uncolor_near_points:
       uncolor_near_points.append((x, y))
  for p in uncolor_near_points:
   if self._can_fliped(p, color):
    yield p

# 測試
if __name__ == '__main__':
 board = Board()
 board.print_b()
 print(list(board.get_legal_actions('X')))

player.py

from ai import AI

'''
作者:hhh6460
時間:2017年7月1日
'''

# 玩家
class Player(object):
 def __init__(self, color):
  self.color = color
  
 # 思考
 def think(self, board):
  pass
  
 # 落子
 def move(self, board, action):
  flipped_pos = board._move(action, self.color)
  return flipped_pos
  
 # 悔子
 def unmove(self, board, action, flipped_pos):
  board._unmove(action, flipped_pos, self.color)


# 人類玩家
class HumanPlayer(Player):
 def __init__(self, color):
  super().__init__(color)
 
 def think(self, board):
  while True:
   action = input("Turn to '{}'. \nPlease input a point.(such as 'A1'): ".format(self.color)) # A1~H8
   r, c = action[1], action[0].upper()
   if r in '12345678' and c in 'ABCDEFGH': # 合法性檢查1
    x, y = '12345678'.index(r), 'ABCDEFGH'.index(c)
    if (x,y) in board.get_legal_actions(self.color): # 合法性檢查2
     return x, y


# 電腦玩家(多重繼承)
class AIPlayer(Player, AI):
 
 def __init__(self, color, level_ix=0):
  super().__init__(color)    # init Player
  super(Player, self).__init__(level_ix) # init AI
  
 
 def think(self, board):
  print("Turn to '{}'. \nPlease wait a moment. AI is thinking...".format(self.color))
  uncolor = ['X','O'][self.color=='X']
  opfor = AIPlayer(uncolor) # 假想敵,陪練
  action = self.brain(board, opfor, 4)
  return action

ai.py

import random

'''
作者:hhh6460
時間:2017年7月1日
'''

class AI(object):
 '''
 三個水平等級:初級(beginner)、中級(intermediate)、高級(advanced)
 '''
 def __init__(self, level_ix =0):
  # 玩家等級
  self.level = ['beginner','intermediate','advanced'][level_ix]
  # 棋盤位置權重,參考:https://github.com/k-time/ai-minimax-agent/blob/master/ksx2101.py
  self.board_weights = [
   [120, -20, 20, 5, 5, 20, -20, 120],
   [-20, -40, -5, -5, -5, -5, -40, -20],
   [ 20, -5, 15, 3, 3, 15, -5, 20],
   [ 5, -5, 3, 3, 3, 3, -5, 5],
   [ 5, -5, 3, 3, 3, 3, -5, 5],
   [ 20, -5, 15, 3, 3, 15, -5, 20],
   [-20, -40, -5, -5, -5, -5, -40, -20],
   [120, -20, 20, 5, 5, 20, -20, 120]
  ]
  
 # 評估函數(僅根據棋盤位置權重)
 def evaluate(self, board, color):
  uncolor = ['X','O'][color=='X']
  score = 0
  for i in range(8):
   for j in range(8):
    if board[i][j] == color:
     score += self.board_weights[i][j]
    elif board[i][j] == uncolor:
     score -= self.board_weights[i][j]
  return score

 # AI的大腦
 def brain(self, board, opponent, depth):
  if self.level == 'beginer':   # 初級水平
   _, action = self.randomchoice(board)
  elif self.level == 'intermediate': # 中級水平
   _, action = self.minimax(board, opponent, depth)
  elif self.level == 'advanced':  # 高級水平
   _, action = self.minimax_alpha_beta(board, opponent, depth)
  assert action is not None, 'action is None'
  return action
 
 # 隨機選(從合法走法列表中隨機選)
 def randomchoice(self, board):
  color = self.color
  action_list = list(board.get_legal_actions(color))
  return None, random.choice(action_list)
 
 # 極大極小算法,限制深度
 def minimax(self, board, opfor, depth=4): # 其中 opfor 是假想敵、陪練
  '''參考:https://github.com/k-time/ai-minimax-agent/blob/master/ksx2101.py'''
  color = self.color
  
  if depth == 0:
   return self.evaluate(board, color), None
  
  action_list = list(board.get_legal_actions(color))
  if not action_list:
   return self.evaluate(board, color), None
  
  best_score = -100000
  best_action = None

  for action in action_list:
   flipped_pos = self.move(board, action) # 落子
   score, _ = opfor.minimax(board, self, depth-1) # 深度優先,輪到陪練
   self.unmove(board, action, flipped_pos) # 回溯
   
   score = -score
   if score > best_score:
    best_score = score
    best_action = action

  return best_score, best_action
  
 # 極大極小算法,帶alpha-beta剪枝
 def minimax_alpha_beta(self, board, opfor, depth=8, my_best=-float('inf'), opp_best=float('inf')):
  '''參考:https://github.com/k-time/ai-minimax-agent/blob/master/ksx2101.py'''
  color = self.color
  
  if depth == 0:
   return self.evaluate(board, color), None
  
  action_list = list(board.get_legal_actions(color))
  if not action_list:
   return self.evaluate(board, color), None
  
  best_score = my_best
  best_action = None
  
  for action in action_list:
   flipped_pos = self.move(board, action) # 落子
   score, _ = opfor.minimax_alpha_beta(board, self, depth-1, -opp_best, -best_score) # 深度優先,輪到陪練
   self.unmove(board, action, flipped_pos) # 回溯
   
   score = -score
   if score > best_score:
    best_score = score
    best_action = action
    
   if best_score > opp_best:
    break

  return best_score, best_action

othello.py

from board import Board
from player import HumanPlayer, AIPlayer

'''
作者:hhh6460
時間:2017年7月1日
'''

# 游戲
class Game(object):
 def __init__(self):
  self.board = Board()
  self.current_player = None
  
 # 生成兩個玩家
 def make_two_players(self):
  ps = input("Please select two player's type:\n\t0.Human\n\t1.AI\nSuch as:0 0\n:")
  p1, p2 = [int(p) for p in ps.split(' ')]
  if p1 == 1 or p2 == 1: # 至少有一個AI玩家
   level_ix = int(input("Please select the level of AI player.\n\t0: beginner\n\t1: intermediate\n\t2: advanced\n:"))
   if p1 == 0:
    player1 = HumanPlayer('X')
    player2 = AIPlayer('O', level_ix)
   elif p2 == 0:
    player1 = AIPlayer('X', level_ix)
    player2 = HumanPlayer('O')
   else:
    player1 = AIPlayer('X', level_ix)
    player2 = AIPlayer('O', level_ix)
  else:
   player1, player2 = HumanPlayer('X'), HumanPlayer('O') # 先手執X,后手執O
  
  return player1, player2
 
 
 # 切換玩家(游戲過程中)
 def switch_player(self, player1, player2):
  if self.current_player is None:
   return player1
  else:
   return [player1, player2][self.current_player == player1]
 
 # 打印贏家
 def print_winner(self, winner): # winner in [0,1,2]
  print(['Winner is player1','Winner is player2','Draw'][winner])
 
 # 運行游戲
 def run(self):
  # 生成兩個玩家
  player1, player2 = self.make_two_players()
  
  # 游戲開始
  print('\nGame start!\n')
  self.board.print_b() # 顯示棋盤
  while True:
   self.current_player = self.switch_player(player1, player2) # 切換當前玩家
   
   action = self.current_player.think(self.board) # 當前玩家對棋盤進行思考后,得到招法
   
   if action is not None: 
    self.current_player.move(self.board, action) # 當前玩家執行招法,改變棋盤
   
   self.board.print_b() # 顯示當前棋盤
   
   if self.board.teminate(): # 根據當前棋盤,判斷棋局是否終止
    winner = self.board.get_winner() # 得到贏家 0,1,2
    break
  
  self.print_winner(winner)
  print('Game over!')
  
  self.board.print_history()
 
 
if __name__ == '__main__':
 Game().run()

效果圖

使用python實現翻轉棋游戲的案例

關于“使用python實現翻轉棋游戲的案例”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

基隆市| 吴桥县| 张北县| 阜新市| 陵川县| 台南市| 荥阳市| 陈巴尔虎旗| 五家渠市| 万源市| 博野县| 桑日县| 宁国市| 宽城| 克山县| 大余县| 贵港市| 离岛区| 衡水市| 根河市| 阿尔山市| 肇东市| 响水县| 临海市| 锡林浩特市| 清远市| 淅川县| 长汀县| 房产| 康乐县| 新泰市| 隆尧县| 聂荣县| 新密市| 青铜峡市| 武隆县| 东辽县| 宜良县| 富锦市| 炎陵县| 麻江县|