python井字棋ai,python 井字棋(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日
# 棋盤(pán)
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)) # 加入棋譜
# 撤銷(xiāo)動(dòng)作,拿走棋子
def _unmove(self, action):
self._board[action] = '-'
self._history.pop()
# 棋盤(pán)快照
def get_board_snapshot(self):
return self._board[:]
# 取棋盤(pán)上的合法走法
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
# 打印棋盤(pán)
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í)行走法,改變棋盤(pán)
'''
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)
# 人類(lèi)玩家
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) # 撤銷(xiāo)走法,回溯
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() # 顯示棋盤(pán)
while True:
self.current_player = self.switch_player(player1, player2) # 切換當(dāng)前玩家
action = self.current_player.think(self.board) # 當(dāng)前玩家對(duì)棋盤(pán)進(jìn)行思考后,得到招法
self.current_player.move(self.board, action) # 當(dāng)前玩家執(zhí)行招法,改變棋盤(pán)
self.board.print_b() # 顯示當(dāng)前棋盤(pán)
if self.board.teminate(): # 根據(jù)當(dāng)前棋盤(pán),判斷棋局是否終止
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é)果
[CareerCup] 17.2 Tic Tac Toe 井字棋游戲
17.2 Design an algorithm to figure out if someone has won a game oftic-tac-toe. 這道題讓我們判斷玩家是否能贏井字棋游戲, ...
LeetCode 5275. 找出井字棋的獲勝者 Find Winner on a Tic Tac Toe Game
地址?https://www.acwing.com/solution/LeetCode/content/6670/ 題目描述A 和?B?在一個(gè)?3?x?3?的網(wǎng)格上玩井字棋. 井字棋游戲的規(guī)則如下: ...
python 游戲(井字棋)
1. 游戲思路和流程圖 實(shí)現(xiàn)功能,現(xiàn)實(shí)生活中的井字棋玩法 游戲流程圖 2. 使用模塊和游戲提示 import random def game_info(): print('歡迎來(lái)到井字棋游戲') pr ...
POJ 2361 Tic Tac Toe
題目:給定一個(gè)3*3的矩陣,是一個(gè)井字過(guò)三關(guān)游戲.開(kāi)始為X先走,問(wèn)你這個(gè)是不是一個(gè)合法的游戲.也就是,現(xiàn)在這種情況,能不能出現(xiàn).如果有人贏了,那應(yīng)該立即停止.那么可以知道X的步數(shù)和O的步數(shù)應(yīng)該滿足x= ...
[LeetCode] 348. Design Tic-Tac-Toe 設(shè)計(jì)井字棋游戲
Design a Tic-tac-toe game that is played between two players on a n x n grid. You may assume the fol ...
井字棋(Tic-Tac-Toe)
井字棋介紹:https://en.wikipedia.org/wiki/Tic-tac-toe 井字棋簡(jiǎn)單,但是獲勝策略卻和直覺(jué)不同,四角比中間重要性要高,而且先手有很大的獲勝概率獲勝(先手勝:91, ...
python3 井字棋 GUI - 人機(jī)對(duì)戰(zhàn)、機(jī)器對(duì)戰(zhàn) (threading、tkinter庫(kù))
python3 井字棋 GUI - 人機(jī)對(duì)戰(zhàn).機(jī)器對(duì)戰(zhàn) 功能 GUI界面 人機(jī)對(duì)戰(zhàn)(可選擇機(jī)器先走) 機(jī)器對(duì)戰(zhàn)(50局) 流程圖 內(nèi)核 棋盤(pán) [0][1][2] [3][4][5] [6][7][8] ...
[LeetCode] Design Tic-Tac-Toe 設(shè)計(jì)井字棋游戲
Design a Tic-tac-toe game that is played between two players on a n x n grid. You may assume the fol ...
隨機(jī)推薦
ODCA最佳實(shí)踐翻譯:Architecting Cloud-Aware Applications (一)
Architecting Cloud-Aware Applications ** ODCA(Open Data Center Alliance)最佳實(shí)踐 ** MagicBowen(e.bowen.w ...
H.264中NAL、Slice與frame意思及相互關(guān)系
H.264中NAL.Slice與frame意思及相互關(guān)系 NAL nal_unit_type中的1(非IDR圖像的編碼條帶).2(編碼條帶數(shù)據(jù)分割塊A).3(編碼條帶數(shù)據(jù)分割塊B).4(編碼條帶數(shù)據(jù)分 ...
c++ 類(lèi)名和enum時(shí)重復(fù)時(shí)要在類(lèi)名前加class::
c++ 類(lèi)名和enum時(shí)重復(fù)時(shí)要在類(lèi)名前加class:: 一些不好的習(xí)慣都是用小寫(xiě),但又沒(méi)有區(qū)分開(kāi)token,看看代碼再說(shuō),下面的代碼是我在測(cè)試polymorphism時(shí)寫(xiě)的一部分,怎么也查不出,最后 ...
理解python的元類(lèi)
看了一篇文檔,借鑒一下!寫(xiě)下自己對(duì)python元類(lèi)的理解,歡迎各位大神給出意見(jiàn). 我的理解就是 type用來(lái)創(chuàng)建元類(lèi),元類(lèi)用來(lái)創(chuàng)建類(lèi),類(lèi)用來(lái)創(chuàng)建實(shí)例 這樣一想,是不是可以認(rèn)為元類(lèi)創(chuàng)建類(lèi)的過(guò)程等同于類(lèi)創(chuàng) ...
js流程語(yǔ)句
一.跳轉(zhuǎn)語(yǔ)句1.break; 終止整個(gè)循環(huán),不再進(jìn)行判斷2.continue; 終止本次循環(huán),接著去判斷是否執(zhí)行下次循環(huán) 二.選擇(判斷)結(jié)構(gòu)1.if 如果? ? ? ? ? ? ? ?if(條件1) ...
C#比較兩個(gè)由基本數(shù)據(jù)類(lèi)型構(gòu)成的object類(lèi)型
/// /// 比較查詢(xún)條件 /// public class ModelExtensions { ///
python之打印日志logging
import logging # 簡(jiǎn)單打印日志舉例 logging.basicConfig(level=logging.DEBUG) # 設(shè)置日志級(jí)別,WARN logging.warning('Wa ...
8.0-uC/OS-III臨界段
1.臨界段 (臨界段代碼,也叫臨界區(qū),是指那些必須完整連續(xù)運(yùn)行,不可被打斷的代碼段) 鎖調(diào)度器,可以執(zhí)行ISR,開(kāi)啟調(diào)度器不可執(zhí)行ISR: (1).臨界段代碼,也稱(chēng)作臨界域,是一段不可分割的代碼. u ...
Luogu 2279 [HNOI2003]消防局的設(shè)立 - 貪心
Description 給定一棵樹(shù)形圖, 建若干個(gè)消防站, 消防站能夠覆蓋到距離不超過(guò)2的點(diǎn), 求最少需要建幾個(gè)消防站才能覆蓋所有點(diǎn) Solution 從深度最深的點(diǎn)開(kāi)始, 在它的爺爺節(jié)點(diǎn)上建, 每建 ...
總結(jié)
以上是生活随笔為你收集整理的python井字棋ai,python 井字棋(Tic Tac Toe)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 2021年9月Github优秀项目推荐
- 下一篇: 3D引擎Axiom的选择与学习