Tic Tac Toe就是我们熟悉的井字棋游戏。我们将通过这个游戏,设计出来第一个人工智能(artificial intelligence, AI)程序,它可以对玩家的落子智能地作出相应。当然井字棋游戏地AI并不复杂,只是简单地几行代码而已。
这个游戏的AI可以概括如下:
- 首先,判断是否有能够让计算机获胜的落子位置。如果是,在那里落子;否则,执行步骤2.
- 判断受否有能够让玩家失败的落子位置。如果是,在那里落子,以便堵住玩家;否则,执行步骤3.
- 判断是否还有角(格子1、3、7或者9)为空。如果有,在此处落子;如果没有角为空,那么执行步骤4.
- 判断是否中心(格子5)为空。如果有,在此处落子;否则,执行步骤5。
- 在任意一个边(格子2、3、6或者8)落子。没有其他步骤了,因为如果执行到第5步,边是仅剩的空地了。
该算法在getComputerMove()函数以及getComputerMove()所调用的其他函数中实现。
这里我们用一个简单的数据表示游戏版,也就是一系列的文本。
(一)导入模块
#Tic-Tac-Toe
import random
(二)drawBoard(board):
我们将通过一个函数实现打印游戏棋盘。将board列表传递给drawBoard()函数,根据board列表中的元素进行打印。
#打印棋盘
def drawBoard(board):
#This function prints out the board that it was passed.
#"board" is a list of 10 strings representing the board (ignore index 0)
print(board[7]+'|'+board[8]+'|'+board[9])
print('-+-+-')
print(board[4]+'|'+board[5]+'|'+board[6])
print('-+-+-')
print(board[1]+'|'+board[2]+'|'+board[3])
print('-+-+-')
(三)inputPlayerLetter():
#让玩家来选择X或者是O
def inputPlayerLetter():
#Let the player enter which letter they want to be.
#Return a list with the player's letter as the first item and the computer's letter as the secend.
letter = ' '
while not (letter == 'X' or letter == 'O'):
print('Do you want to be X or O ?')
letter = input().upper()
#The first element in the list is the player 's letter; the secend is the computer's letter.
if letter == 'X':
return ['X', 'O']
else:
return ['O', 'X']
(四)whoGoesFirst():
#决定谁先走
def whoGoesFirst():
#Randomly choose which player goes first.
if random.randint(0, 2) == 0:
return 'computer'
else:
return 'player'
(五)makeMove(board, letter, move):
#在游戏版上放置一个标记
def makeMove(board, letter, move):
board[move] = letter
列表的引用
所谓列表引用,简单理解就是对于列表来说,赋值符号(=)不是代表复制,而是代表对列表的引用。
>>> x = [1, 2, 3, 4]
>>> y = x
>>> y.append(5)
>>> y
[1, 2, 3, 4, 5]
>>> x
[1, 2, 3, 4, 5]
(六)isWinner(bo,le):
#判断玩家是否获胜
def isWinner(bo,le):
return ((bo[7] == le and bo[8] == le and bo[9] == le) or # across the top
(bo[4] == le and bo[5] == le and bo[6] == le) or # across the middle
(bo[1] == le and bo[2] == le and bo[3] == le) or # across the bottom
(bo[7] == le and bo[4] == le and bo[1] == le) or # down the left side
(bo[8] == le and bo[5] == le and bo[2] == le) or # down the middle
(bo[9] == le and bo[6] == le and bo[3] == le) or # down the right side
(bo[7] == le and bo[5] == le and bo[3] == le) or # diagonal
(bo[9] == le and bo[5] == le and bo[1] == le)) # diagonal
(七)getBoardCopy(board):
#复制游戏版的数据
def getBoardCopy(board):
#Make a copy of the board list and return it.
boardCopy = []
for i in board:
boardCopy.append(i)
return boardCopy
(八)isSpaceFree(board, move):
#判断游戏板上的格子是否为空
def isSpaceFree(board, move):
#Return True if the passed move is free on the passed board.
return board[move] == ' '
(九)getPlayerMove(board):
#让玩家输入落子的格子的编号
def getPlayerMove(board):
#Let the player enter their move.
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)
短路求值
短路(short-circuiting)在这里表示由于关键字or左边部分为True,Python解释器就知道整个表达式的计算结果为True。
>>> def ReturnTrue():
print('ReturnTrue() was called')
return True
>>> def ReturnFalse():
print('ReturnFalse() was called')
return False
>>> ReturnTrue()
ReturnTrue() was called
True
>>> ReturnFalse()
ReturnFalse() was called
False
>>> ReturnFalse() or ReturnTrue()
ReturnFalse() was called
ReturnTrue() was called
True
>>> ReturnTrue() or ReturnFalse()
ReturnTrue() was called
True
(十)chooseRandomMoveFromList(board, moveList):
#从落子列表选择一个落子
def chooseRandomMoveFromList(board, moveList):
#Returns a valid move from the passed list on the passed board.
#Returns None if there in no valid move.
possibleMoves = []
for i in moveList:
if isSpaceFree(board, i):
possibleMoves.append(i)
if len(possibleMoves) != 0:
return random.choice(possibleMoves)
else:
return None
(十一)getComputerMove(board, computerLetter):
def getComputerMove(board, computerLetter):
#Given a board and the computer 's letter, determine where to move and return that move.
if computerLetter == 'X':
playerLetter = 'O'
else:
playerLetter = 'X'
#Here is the algorithm for our Tic-Tac-Toe AI:
#First, check if we can win in the next move.
for i in range(0, 10):
boardCopy = getBoardCopy(board)
if isSpaceFree(boardCopy, i):
makeMove(boardCopy, computerLetter, i)
if isWinner(boardCopy, computerLetter):
return i
#Check if the player could win on their next move and blockthem.
for i in range(0, 10):
boardCopy = getBoardCopy(board)
if isSpaceFree(boardCopy, i):
makeMove(boardCopy, playerLetter, i)
if isWinner(boardCopy, playerLetter):
return i
#Try to take one of the corners, if they are free.
move = chooseRandomMoveFromList(board, [1, 3, 7, 9])
if move != None:
return move
#Try to take the center, if it is free.
if isSpaceFree(board, 5):
return 5
#Move on the sides.
return chooseRandomMoveFromList(board, [2, 4, 6, 8])
(十二)isBoardFull(board):
def isBoardFull(board):
#Return True if every space on the board has taken. Otherwise, return False
for i in range(1, 10):
if isSpaceFree(board, i):
return False
return True
(十三)游戏循环
print('Welcome to Tic-Tac-Toe!')
while True:
#Reset the board.
theBoard = [' '] * 10
playerLetter,computerLetter = inputPlayerLetter()
turn = whoGoesFirst()
print('The '+turn+' will go first.')
gameIsplaying = True
while gameIsplaying:
if turn == 'player':
#Player's turn
drawBoard(theBoard)
move = getPlayerMove(theBoard)
makeMove(theBoard, playerLetter, move)
print(theBoard)
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:
#Computer's turn
move = getComputerMove(theBoard, computerLetter)
makeMove(theBoard, computerLetter, move)
print(theBoard)
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'
print('Do you want to play again ?(yes or no)')
if not input().lower().startswith('y'):
break
源代码:
#Tic-Tac-Toe
import random
#打印棋盘
def drawBoard(board):
#This function prints out the board that it was passed.
#"board" is a list of 10 strings representing the board (ignore index 0)
print(board[7]+'|'+board[8]+'|'+board[9])
print('-+-+-')
print(board[4]+'|'+board[5]+'|'+board[6])
print('-+-+-')
print(board[1]+'|'+board[2]+'|'+board[3])
print('-+-+-')
#让玩家来选择X或者是O
def inputPlayerLetter():
#Let the player enter which letter they want to be.
#Return a list with the player's letter as the first item and the computer's letter as the secend.
letter = ' '
while not (letter == 'X' or letter == 'O'):
print('Do you want to be X or O ?')
letter = input().upper()
#The first element in the list is the player 's letter; the secend is the computer's letter.
if letter == 'X':
return ['X', 'O']
else:
return ['O', 'X']
#决定谁先走
def whoGoesFirst():
#Randomly choose which player goes first.
if random.randint(0, 2) == 0:
return 'computer'
else:
return 'player'
#在游戏版上放置一个标记
def makeMove(board, letter, move):
board[move] = letter
#判断玩家是否获胜
def isWinner(bo,le):
return ((bo[7] == le and bo[8] == le and bo[9] == le) or # across the top
(bo[4] == le and bo[5] == le and bo[6] == le) or # across the middle
(bo[1] == le and bo[2] == le and bo[3] == le) or # across the bottom
(bo[7] == le and bo[4] == le and bo[1] == le) or # down the left side
(bo[8] == le and bo[5] == le and bo[2] == le) or # down the middle
(bo[9] == le and bo[6] == le and bo[3] == le) or # down the right side
(bo[7] == le and bo[5] == le and bo[3] == le) or # diagonal
(bo[9] == le and bo[5] == le and bo[1] == le)) # diagonal
#复制游戏版的数据
def getBoardCopy(board):
#Make a copy of the board list and return it.
boardCopy = []
for i in board:
boardCopy.append(i)
return boardCopy
#判断游戏板上的格子是否为空
def isSpaceFree(board, move):
#Return True if the passed move is free on the passed board.
return board[move] == ' '
#让玩家输入落子的格子的编号
def getPlayerMove(board):
#Let the player enter their move.
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, moveList):
#Returns a valid move from the passed list on the passed board.
#Returns None if there in no valid move.
possibleMoves = []
for i in moveList:
if isSpaceFree(board, i):
possibleMoves.append(i)
if len(possibleMoves) != 0:
return random.choice(possibleMoves)
else:
return None
def getComputerMove(board, computerLetter):
#Given a board and the computer 's letter, determine where to move and return that move.
if computerLetter == 'X':
playerLetter = 'O'
else:
playerLetter = 'X'
#Here is the algorithm for our Tic-Tac-Toe AI:
#First, check if we can win in the next move.
for i in range(0, 10):
boardCopy = getBoardCopy(board)
if isSpaceFree(boardCopy, i):
makeMove(boardCopy, computerLetter, i)
if isWinner(boardCopy, computerLetter):
return i
#Check if the player could win on their next move and blockthem.
for i in range(0, 10):
boardCopy = getBoardCopy(board)
if isSpaceFree(boardCopy, i):
makeMove(boardCopy, playerLetter, i)
if isWinner(boardCopy, playerLetter):
return i
#Try to take one of the corners, if they are free.
move = chooseRandomMoveFromList(board, [1, 3, 7, 9])
if move != None:
return move
#Try to take the center, if it is free.
if isSpaceFree(board, 5):
return 5
#Move on the sides.
return chooseRandomMoveFromList(board, [2, 4, 6, 8])
def isBoardFull(board):
#Return True if every space on the board has taken. Otherwise, return False
for i in range(1, 10):
if isSpaceFree(board, i):
return False
return True
print('Welcome to Tic-Tac-Toe!')
while True:
#Reset the board.
theBoard = [' '] * 10
playerLetter,computerLetter = inputPlayerLetter()
turn = whoGoesFirst()
print('The '+turn+' will go first.')
gameIsplaying = True
while gameIsplaying:
if turn == 'player':
#Player's turn
drawBoard(theBoard)
move = getPlayerMove(theBoard)
makeMove(theBoard, playerLetter, move)
print(theBoard)
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:
#Computer's turn
move = getComputerMove(theBoard, computerLetter)
makeMove(theBoard, computerLetter, move)
print(theBoard)
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'
print('Do you want to play again ?(yes or no)')
if not input().lower().startswith('y'):
break