我正在努力学习python,并一直试图编程一个简单的tictactoe游戏。以下是代码。
import random
class TicTacToe03:
def __init__(self):
# first, the board
self.board = self.board = [" ", " ", " ", " ", " ", " ", " ", " ", " "]
# then, the symbols the players will choose
self.playerSymbol = ""
self.aiSymbol = ""
# the game is always ongoing, unless somebody won
self.gameOngoing = True
# you also need to tell the ai how different conditions are evaluated
self.scoreBoard = {
self.playerSymbol: -10, # if the player wins, it is seen as smth bad from the ai
self.aiSymbol: 10,
"tie": 0
}
# every tictactoe game starts by drawing the board
def drawBoard(self):
print("""
{} | {} | {}
-----------
{} | {} | {}
-----------
{} | {} | {}
""".format(*self.board))
# then, eveybody chooses what the like
def chooseYourPlayer(self):
self.playerSymbol = input("choose your player X/O ").upper()
if self.playerSymbol == "X":
self.aiSymbol = "O"
else:
self.aiSymbol = "X"
# everybody has to behave and leave their turn when it's over
def nextPlayer(self, player):
if player == self.playerSymbol:
return self.aiSymbol
return self.playerSymbol
# ppl also have to be able to make moves
def move(self, player, index):
self.board[index] = player
# and find what moves they CAN make, so they don't override each-other
def availableMoves(self):
availableMoves = []
for fieldIndex in range(len(self.board)):
if self.board[fieldIndex] == " ":
availableMoves.append(fieldIndex) # yes, i append indexes, not empty fields
return availableMoves
def getMoves(self, player):
playerMoves = []
for fieldIndex in range(len(self.board)):
if self.board[fieldIndex] == player:
playerMoves.append(fieldIndex)
return playerMoves
# here is the algo to check who won, based on a set of winPos is subset of playerMoves
def won(self):
winningPositions = [{0, 1, 2}, {3, 4, 5}, {6, 7, 8},
{0, 4, 8}, {2, 4, 6}, {0, 3, 6},
{1, 4, 7}, {2, 5, 8}]
for player in ("X", "O"):
playerPositions = self.getMoves(player)
for position in winningPositions:
if position.issubset(playerPositions):
print(player + "wins")
self.gameOngoing = False
return player
if self.board.count(" ") == 0: # and this dude outside of the main loop
print("Guess it's a draw")
self.gameOngoing = False
return "tie"
def minimax(self, isMaximizing, player):
if not self.gameOngoing: # base in minimax: if this is an end-state, return it's evaluation
return self.scoreBoard[self.won()]
if isMaximizing:
bestScore = float("-Infinity") # the worst eval for max
for move in self.availableMoves():
self.move(player, move)
score = self.minimax(False, self.nextPlayer(player)) # you should pick the max of what your opponent chooses
self.move(" ", move)
bestScore = max(bestScore, score)
return bestScore
else:
bestScore = float("Infinity")
for move in self.availableMoves():
self.move(player, move)
score = self.minimax(True, self.nextPlayer(player))
self.move(" ", move)
bestScore = min(bestScore, score)
return bestScore
def findOptimalMove(self, player):
goldenMiddle = 0
choices = []
for move in self.availableMoves():
self.move(player, move)
score = self.minimax(True, player)
self.move(" ", move)
if score > goldenMiddle:
choices = [move] # this is a one-element list
break
elif score == goldenMiddle:
choices.append(move)
# here is the code block that mustn't be wrongly interpreted:
# the idea is: you choose a random element, from a ONE-ELEMENT list!!!
if len(choices) > 0:
return random.choice(choices)
else:
return random.choice(self.availableMoves())
def play(self):
self.chooseYourPlayer()
while self.gameOngoing:
personMove = int(input("Choose a position (1-9) "))
self.move(self.playerSymbol, personMove - 1)
self.drawBoard()
if not self.gameOngoing:
break
print("Computer choosing move...")
aiMove = self.findOptimalMove(self.aiSymbol)
self.move(self.aiSymbol, aiMove)
self.drawBoard()
print("Thanks for playing :)")
tictactoe = TicTacToe03()
tictactoe.play()
游戏 "工作 "了,因为它显示了用户的字段,然而它不会显示是否有人赢了。正如你所看到的,我尝试了简单的最小化算法,但也不能正常工作,因为人工智能只是选择下一个可用的字段,而不是逻辑上应该选择的字段。
至于我得到的错误:我只得到了一次,在板子满了之后,它是以下内容。IndexError: Cannot choose from an empty sequence (IndexError): Cannot choose from an empty sequence (on line 133).
我还发布了另一个版本,其中 "中奖 "问题不存在 ( TicTacToe和Minimax。 ),但由于没有人回答这个问题,我想再问一次会有帮助(如果我做错了什么,对不起)
一如既往,我对改进我的代码的建议和方法持开放态度 :)
在我看来,唯一的问题是你忘记了调用 self.won()
在 play()
方法。
def play(self):
self.chooseYourPlayer()
while self.gameOngoing:
personMove = int(input("Choose a position (1-9) "))
self.move(self.playerSymbol, personMove - 1)
self.drawBoard()
self.won() #<--- call self.won() here
if not self.gameOngoing:
break
print("Computer choosing move...")
aiMove = self.findOptimalMove(self.aiSymbol)
self.move(self.aiSymbol, aiMove)
self.drawBoard()
print("Thanks for playing :)")
我想你曾试图做类似的事情在 minimax()
方法。但我不明白你说的是什么意思。
if not self.gameOngoing:
return self.scoreBoard[self.won()]