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
作者:_低头写作业