python井字棋
用python寫井字棋小游戲
井字棋簡介:井字棋又稱三子棋,英文名為Tic Tac Toe。具體玩法為在一個(gè)3x3的棋盤上,一個(gè)玩家用X做棋子,另一個(gè)玩家用O做棋子,誰先在棋盤上的一行、一列或?qū)蔷€上畫滿三個(gè)棋子,即可獲勝,如果棋盤下滿無人勝出,即為平局。
井字棋在與電腦對(duì)戰(zhàn)時(shí)涉及到了簡單的人工智能,人工智能分為四個(gè)等級(jí):
巔峰級(jí)——已經(jīng)實(shí)現(xiàn)了無法超越的最優(yōu)能力
超越人類級(jí)——比所有人類的能力都要強(qiáng)
強(qiáng)人類級(jí)——比大多數(shù)人類的能力要強(qiáng)
弱人類級(jí)——比大多數(shù)人類的能力要弱
而在井字棋下的人工智能可以達(dá)到巔峰級(jí)—————人類永遠(yuǎn)無法戰(zhàn)勝電腦。這是游戲本身性質(zhì)所導(dǎo)致,同齡人之間下井字棋,多下幾把后便很難出現(xiàn)勝方,只要掌握了其中的套路,認(rèn)真一下,就不再會(huì)輸了。
這是游戲設(shè)計(jì)的流程圖,源代碼也是按照這個(gè)思路來的。
關(guān)于落子問題
由于只能采用鍵盤輸入,所以需要對(duì)棋盤進(jìn)行坐標(biāo)表示。有兩種方式,一種是用橫豎坐標(biāo)來表示,這種方法常見于圍棋和五子棋中。井字棋是一種簡單的棋盤游戲,只有9個(gè)棋子位,所以用另一種更簡單的表示方法,即直接用1-9個(gè)9個(gè)數(shù)字來表示位置,其索引順序與鍵盤上的數(shù)字鍵排列一致,下棋時(shí)看著數(shù)字鍵下,較為簡便。
計(jì)算機(jī)的算法--尋找最佳落子位置
首先簡單的將棋盤劃分為三個(gè)部分——中心(1),角(4),邊(4)。中心雖然只有一個(gè)但卻不是最重要的,三個(gè)部分落子的優(yōu)先順序依次為:角、中心、邊。這是關(guān)于井字棋最有算法的相關(guān)文章鏈接,請(qǐng)自行查閱,http://www.guokr.com/article/4754/
因此,井字棋的AI算法計(jì)算最佳落子位置的順序如下:
直接落子獲勝
阻止玩家獲勝
在角上落子
在中心落子
在邊上落子
程序源代碼
# Tic Tac Toe
?
?
import random
?
?
def drawBoard(board):
? ? # 打印棋盤
?
?
? ? # "board"是長度為10的列表,為了方便輸入,忽略第一個(gè)元素board[0]
?
?
? ? print('\n\n\n\n')
? ? print('\t\t\t┌─┬─┬─┐')
? ? print('\t\t\t│'+board[7]+' │'+board[8]+' │'+board[9]+' │')
? ? print('\t\t\t├─┼─┼─┤')
? ? print('\t\t\t│'+board[4]+' │'+board[5]+' │'+board[6]+' │')
? ? print('\t\t\t├─┼─┼─┤')
? ? print('\t\t\t│'+board[1]+' │'+board[2]+' │'+board[3]+' │')
? ? print('\t\t\t└─┴─┴─┘')
?
?
def inputPlayerLetter():
? ? # 讓玩家選擇棋子
? ? # 返回一個(gè)列表,第一個(gè)是玩家的棋子,第二個(gè)是電腦的
? ? letter = ''
? ? while not (letter == 'X' or letter == 'O'):
? ? ? ? print('Do you want to be X or O?')
? ? ? ? letter = input().upper()
?
?
? ? if letter == 'X':
? ? ? ? return ['X', 'O']
? ? else:
? ? ? ? return ['O', 'X']
?
?
def whoGoesFirst():
? ? # 隨機(jī)產(chǎn)生誰先走
? ? if random.randint(0, 1) == 0:
? ? ? ? return 'computer'
? ? else:
? ? ? ? return 'player'
?
?
def playAgain():
? ? # 再玩一次?輸入yes或y返回True
? ? print('Do you want to play again? (yes or no)')
? ? return input().lower().startswith('y')
?
?
def makeMove(board, letter, move):
? ? #落子
? ? board[move] = letter
?
?
def isWinner(bo, le):
? ? # 判斷所給的棋子是否獲勝
? ? # 參數(shù)為棋盤上的棋子(列表)和棋子符號(hào)
? ? # 以下是所有可能勝利的情況,共8種
? ? return ((bo[7] == le and bo[8] == le and bo[9] == le) or?
? ? (bo[4] == le and bo[5] == le and bo[6] == le) or?
? ? (bo[1] == le and bo[2] == le and bo[3] == le) or?
? ? (bo[7] == le and bo[4] == le and bo[1] == le) or?
? ? (bo[8] == le and bo[5] == le and bo[2] == le) or?
? ? (bo[9] == le and bo[6] == le and bo[3] == le) or
? ? (bo[7] == le and bo[5] == le and bo[3] == le) or
? ? (bo[9] == le and bo[5] == le and bo[1] == le))?
?
?
def getBoardCopy(board):
? ? # 復(fù)制一份棋盤,供電腦落子時(shí)使用
? ? dupeBoard = []
?
?
? ? for i in board:
? ? ? ? dupeBoard.append(i)
?
?
? ? return dupeBoard
?
?
def isSpaceFree(board, move):
? ? # 判斷這個(gè)位置是否有子,沒子返回True
? ? return board[move] == ' '
?
?
def getPlayerMove(board):
? ? # 玩家落子
? ? move = ' '
? ? while move not in '1 2 3 4 5 6 7 8 9'.split() or not isSpaceFree(board, int(move)):
? ? ? ? print('What is your next move? (1-9)')
? ? ? ? move = input()
? ? return int(move)
?
?
def chooseRandomMoveFromList(board, movesList):
? ? # 隨機(jī)返回一個(gè)可以落子的坐標(biāo)
? ? # 如果沒有所給的movesList中沒有可以落子的,返回None
? ? possibleMoves = []
? ? for i in movesList:
? ? ? ? if isSpaceFree(board, i):
? ? ? ? ? ? possibleMoves.append(i)
?
?
? ? if len(possibleMoves) != 0:
? ? ? ? return random.choice(possibleMoves)
? ? else:
? ? ? ? return None
?
?
def getComputerMove(board, computerLetter):
? ? # 確定電腦的落子位置
? ? if computerLetter == 'X':
? ? ? ? playerLetter = 'O'
? ? else:
? ? ? ? playerLetter = 'X'
?
?
? ? # Tic Tac Toe AI核心算法:
? ? # 首先判斷電腦方能否通過一次落子直接獲得游戲勝利
? ? for i in range(1, 10):
? ? ? ? copy = getBoardCopy(board)
? ? ? ? if isSpaceFree(copy, i):
? ? ? ? ? ? makeMove(copy, computerLetter, i)
? ? ? ? ? ? if isWinner(copy, computerLetter):
? ? ? ? ? ? ? ? return i
?
?
? ? # 判斷玩家下一次落子能否獲得勝利,如果能,給它堵上
? ? for i in range(1, 10):
? ? ? ? copy = getBoardCopy(board)
? ? ? ? if isSpaceFree(copy, i):
? ? ? ? ? ? makeMove(copy, playerLetter, i)
? ? ? ? ? ? if isWinner(copy, playerLetter):
? ? ? ? ? ? ? ? return i
?
?
? ? # 如果角上能落子的話,在角上落子
? ? move = chooseRandomMoveFromList(board, [1, 3, 7, 9])
? ? if move != None:
? ? ? ? return move
?
?
? ? # 如果能在中心落子的話,在中心落子
? ? if isSpaceFree(board, 5):
? ? ? ? return 5
?
?
? ? # 在邊上落子
? ? return chooseRandomMoveFromList(board, [2, 4, 6, 8])
?
?
def isBoardFull(board):
? ? # 如果棋盤滿了,返回True
? ? for i in range(1, 10):
? ? ? ? if isSpaceFree(board, i):
? ? ? ? ? ? return False
? ? return True
?
?
?
?
print('Welcome to Tic Tac Toe!')
?
?
while True:
? ? # 更新棋盤
? ? theBoard = [' '] * 10
? ? playerLetter, computerLetter = inputPlayerLetter()
? ? turn = whoGoesFirst()
? ? print('The ' + turn + ' will go first.')
? ? gameIsPlaying = True
?
?
? ? while gameIsPlaying:
? ? ? ? if turn == 'player':
? ? ? ? ? ? # 玩家回合
? ? ? ? ? ? drawBoard(theBoard)
? ? ? ? ? ? move = getPlayerMove(theBoard)
? ? ? ? ? ? makeMove(theBoard, playerLetter, move)
?
?
? ? ? ? ? ? if isWinner(theBoard, playerLetter):
? ? ? ? ? ? ? ? drawBoard(theBoard)
? ? ? ? ? ? ? ? print('Hooray! You have won the game!')
? ? ? ? ? ? ? ? gameIsPlaying = False
? ? ? ? ? ? else:
? ? ? ? ? ? ? ? if isBoardFull(theBoard):
? ? ? ? ? ? ? ? ? ? drawBoard(theBoard)
? ? ? ? ? ? ? ? ? ? print('The game is a tie!')
? ? ? ? ? ? ? ? ? ? break
? ? ? ? ? ? ? ? else:
? ? ? ? ? ? ? ? ? ? turn = 'computer'
?
?
? ? ? ? else:
? ? ? ? ? ? # 電腦回合
? ? ? ? ? ? move = getComputerMove(theBoard, computerLetter)
? ? ? ? ? ? makeMove(theBoard, computerLetter, move)
?
?
? ? ? ? ? ? if isWinner(theBoard, computerLetter):
? ? ? ? ? ? ? ? drawBoard(theBoard)
? ? ? ? ? ? ? ? print('The computer has beaten you! You lose.')
? ? ? ? ? ? ? ? gameIsPlaying = False
? ? ? ? ? ? else:
? ? ? ? ? ? ? ? if isBoardFull(theBoard):
? ? ? ? ? ? ? ? ? ? drawBoard(theBoard)
? ? ? ? ? ? ? ? ? ? print('The game is a tie!')
? ? ? ? ? ? ? ? ? ? break
? ? ? ? ? ? ? ? else:
? ? ? ? ? ? ? ? ? ? turn = 'player'
?
?
? ? if not playAgain():
? ? ? ? break
————————————————
版權(quán)聲明:本文為CSDN博主「極度寒空」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_39035741/article/details/77101765
總結(jié)
- 上一篇: php判断是否是节假日,C#编程之C#判
- 下一篇: python照片转化立体_3-Sweep