Python實(shí)現(xiàn)的井字棋(Tic Tac Toe)游戲示例
本文實(shí)例講述了Python實(shí)現(xiàn)的井字棋(Tic Tac Toe)游戲。分享給大家供大家參考,具體如下:
說(shuō)明
用python實(shí)現(xiàn)了井字棋,整個(gè)框架是本人自己構(gòu)思的,自認(rèn)為比較滿意。另外,90%+的代碼也是本人逐字逐句敲的。
minimax算法還沒(méi)完全理解,所以參考了這里的代碼,并作了修改。
特點(diǎn)
可以選擇人人、人機(jī)、機(jī)人、機(jī)機(jī)四種對(duì)戰(zhàn)模式之一
電腦玩家的AI使用了minimax算法,帶apha-beta剪枝
電腦玩家在思考時(shí),時(shí)時(shí)刻刻都有一個(gè)“假想敵”。以便使得minimax算法運(yùn)轉(zhuǎn)起來(lái)
代碼
#作者:hhh5460
#時(shí)間:2017年6月26日
# 棋盤
class Board(object):
def __init__(self):
#self._board = '-'*9 # 坑??!
self._board = ['-' for _ in range(9)]
self._history = [] # 棋譜
# 按指定動(dòng)作,放入棋子
def _move(self, action, take):
if self._board[action] == '-':
self._board[action] = take
self._history.append((action, take)) # 加入棋譜
# 撤銷動(dòng)作,拿走棋子
def _unmove(self, action):
self._board[action] = '-'
self._history.pop()
# 棋盤快照
def get_board_snapshot(self):
return self._board[:]
# 取棋盤上的合法走法
def get_legal_actions(self):
actions = []
for i in range(9):
if self._board[i] == '-':
actions.append(i)
return actions
# 判斷走法是否合法
def is_legal_action(self, action):
return self._board[action] == '-'
# 終止檢測(cè)
def teminate(self):
board = self._board
lines = [board[0:3], board[3:6], board[6:9], board[0::3], board[1::3], board[2::3], board[0::4], board[2:7:2]]
if ['X']*3 in lines or ['O']*3 in lines or '-' not in board:
return True
else:
return False
# 勝負(fù)檢查
def get_winner(self):
board = self._board
lines = [board[0:3], board[3:6], board[6:9], board[0::3], board[1::3], board[2::3], board[0::4], board[2:7:2]]
if ['X']*3 in lines:
return 0
elif ['O']*3 in lines:
return 1
else:
return 2
# 打印棋盤
def print_b(self):
board = self._board
for i in range(len(board)):
print(board[i], end='')
if (i+1)%3 == 0:
print()
# 打印棋譜
def print_history(self):
print(self._history)
# 玩家
class Player(object):
'''
玩家只做兩件事:思考、落子
1. 思考 --> 得到走法
2. 落子 --> 執(zhí)行走法,改變棋盤
'''
def __init__(self, take='X'): # 默認(rèn)執(zhí)的棋子為 take = 'X'
self.take=take
def think(self, board):
pass
def move(self, board, action):
board._move(action, self.take)
# 人類玩家
class HumanPlayer(Player):
def __init__(self, take):
super().__init__(take)
def think(self, board):
while True:
action = input('Please input a num in 0-8:')
if len(action)==1 and action in '012345678' and board.is_legal_action(int(action)):
return int(action)
# 電腦玩家
class AIPlayer(Player):
def __init__(self, take):
super().__init__(take)
def think(self, board):
print('AI is thinking ...')
take = ['X','O'][self.take=='X']
player = AIPlayer(take) # 假想敵?。?!
_, action = self.minimax(board, player)
#print('OK')
return action
# 極大極小法搜索,α-β剪枝
def minimax(self, board, player, depth=0) :
'''參考:https://stackoverflow.com/questions/44089757/minimax-algorithm-for-tic-tac-toe-python'''
if self.take == "O":
bestVal = -10
else:
bestVal = 10
if board.teminate() :
if board.get_winner() == 0 :
return -10 + depth, None
elif board.get_winner() == 1 :
return 10 - depth, None
elif board.get_winner() == 2 :
return 0, None
for action in board.get_legal_actions() : # 遍歷合法走法
board._move(action, self.take)
val, _ = player.minimax(board, self, depth+1) # 切換到 假想敵?。。?
board._unmove(action) # 撤銷走法,回溯
if self.take == "O" :
if val > bestVal:
bestVal, bestAction = val, action
else :
if val < bestVal:
bestVal, bestAction = val, action
return bestVal, bestAction
# 游戲
class Game(object):
def __init__(self):
self.board = Board()
self.current_player = None
# 生成玩家
def mk_player(self, p, take='X'): # p in [0,1]
if p==0:
return HumanPlayer(take)
else:
return AIPlayer(take)
# 切換玩家
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])
# 運(yùn)行游戲
def run(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(' ')]
player1, player2 = self.mk_player(p1, 'X'), self.mk_player(p2, 'O') # 先手執(zhí)X,后手執(zhí)O
print('\nGame start!\n')
self.board.print_b() # 顯示棋盤
while True:
self.current_player = self.switch_player(player1, player2) # 切換當(dāng)前玩家
action = self.current_player.think(self.board) # 當(dāng)前玩家對(duì)棋盤進(jìn)行思考后,得到招法
self.current_player.move(self.board, action) # 當(dāng)前玩家執(zhí)行招法,改變棋盤
self.board.print_b() # 顯示當(dāng)前棋盤
if self.board.teminate(): # 根據(jù)當(dāng)前棋盤,判斷棋局是否終止
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()
下圖是人人對(duì)戰(zhàn)的結(jié)果

更多關(guān)于Python相關(guān)內(nèi)容可查看本站專題:《Python游戲開發(fā)技巧總結(jié)》、《Python數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Python Socket編程技巧總結(jié)》、《Python函數(shù)使用技巧總結(jié)》、《Python字符串操作技巧匯總》、《Python入門與進(jìn)階經(jīng)典教程》及《Python文件與目錄操作技巧匯總》
希望本文所述對(duì)大家Python程序設(shè)計(jì)有所幫助。
相關(guān)文章
python各層級(jí)目錄下import方法代碼實(shí)例
這篇文章主要介紹了python各層級(jí)目錄下import方法代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-01-01
Python實(shí)現(xiàn)數(shù)據(jù)透視表詳解
今天小編就為大家分享一篇用Python實(shí)現(xiàn)數(shù)據(jù)的透視表的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-10-10
python concurrent.futures模塊的使用測(cè)試
大家都知道concurrent.futures 是 3.2 中引入的新模塊,它為異步執(zhí)行可調(diào)用對(duì)象提供了高層接口,今天通過(guò)本文給大家介紹python concurrent.futures模塊的使用測(cè)試 ,感興趣的朋友一起看看吧2021-07-07
Python selenium模塊實(shí)現(xiàn)定位過(guò)程解析
這篇文章主要介紹了python selenium模塊實(shí)現(xiàn)定位過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07
Python實(shí)現(xiàn)批量提取PPT中的文字
這篇文章主要為大家詳細(xì)介紹了如何使用Python中的pptx和docx庫(kù)來(lái)將PPT中的文字提取到Word中,文中的示例代碼講解詳細(xì),有需要的可以參考下2024-03-03
PyTorch加載模型model.load_state_dict()問(wèn)題及解決
這篇文章主要介紹了PyTorch加載模型model.load_state_dict()問(wèn)題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。2023-02-02
利用Python實(shí)現(xiàn)批量打包程序的工具
auto-py-to-exe與pyinstaller都無(wú)法直接一次性打包多個(gè)程序,想打包多個(gè)程序需要重新操作一遍。所以本文將用Python實(shí)現(xiàn)批量打包程序的工具,感興趣的可以了解一下2022-07-07

