I came up with a simple AI for a Tic-Tac-Toe game that should cause the computer opponent to try to block my moves. Running the code brings up no errors, and the computer usually blocks me. However, it sometimes moves in a random spot on the board. Also, some of the pieces on the board will disappear. Any help?
import operator, sys, random, time
def GameLoop():
def allEqual(list):
# Returns True if all the elements in a list are equal, or if the list is empty.
return not list or list == [list[0]] * len(list)
Empty = ' '
Player_X = 'X'
Player_O = 'O'
class Board:
# This class represents a tic tac toe board state.
def __init__(self):
"""Initialize all members."""
self.pieces = [Empty]*9
self.field_names = '123456789'
def output(self):
# Display the board on screen.
print('',self.pieces[0],'|',self.pieces[1],'|',self.pieces[2])
print('-----------')
print('',self.pieces[3],'|',self.pieces[4],'|',self.pieces[5])
print('-----------')
print('',self.pieces[6],'|',self.pieces[7],'|',self.pieces[8])
print()
def winner(self):
# Determine if one player has won the game. Returns Player_X, Player_O or None.
winning_rows = [[0,1,2],[3,4,5],[6,7,8], # Vertical
[0,3,6],[1,4,7],[2,5,8], # Horizontal
[0,4,8],[2,4,6]] # Diagonal
for row in winning_rows:
if self.pieces[row[0]] != Empty and allEqual([self.pieces[i] for i in row]):
return self.pieces[row[0]]
def getValidMoves(self):
# Returns a list of valid moves. A move can be passed to getMoveName to
# Retrieve a human-readable name or to makeMove/undoMove to play it.
return [pos for pos in range(9) if self.pieces[pos] == Empty]
def gameOver(self):
# Returns true if one player has won or if there are no valid moves left.
return self.winner() or not self.getValidMoves()
def getMoveName(self, move):
# Returns a human-readable name for a move
return self.field_names[move]
def makeMove(self, move, player):
# Plays a move. Note: this doesn't check if the move is legal!
self.pieces[move] = player
def undoMove(self, move):
# Undoes a move/removes a piece of the board.
self.makeMove(move, Empty)
def humanPlayer(board, player):
global move
# Function for the human player.
board.output()
possible_moves = dict([(board.getMoveName(move), move) for move in board.getValidMoves()])
move = input("Enter your move, pathetic human! (%s): " % (', '.join(sorted(possible_moves))))
while move not in possible_moves:
print("Silly human, '%s' is not a valid move! Try again!" % move)
move = input("Enter your move, pathetic human! (%s): " % (', '.join(sorted(possible_moves))))
board.makeMove(possible_moves[move], player)
def computerPlayer(board, player):
# Function for the computer player.
t0 = time.time()
board.output()
opponent = { Player_O : Player_X, Player_X : Player_O }
def judge(winner):
if winner == player:
return +1
if winner == None:
return 0
return -1
def evaluateMove(move, p=player):
try:
board.makeMove(move, p)
if board.gameOver():
return judge(board.winner())
outcomes = (evaluateMove(next_move, opponent[p]) for next_move in board.getValidMoves())
if p == player:
#return min(outcomes)
min_element = 1
for o in outcomes:
if o == -1:
return o
min_element = min(o,min_element)
return min_element
else:
#return max(outcomes)
max_element = -1
for o in outcomes:
if o == +1:
return o
max_element = max(o,max_element)
return max_element
finally:
board.undoMove(move)
if move == "1":
movef = random.choice("13")
moveg = int(movef)
elif move == "2":
movef = random.choice("024")
moveg = int(movef)
elif move == "3":
movef = random.choice("15")
moveg = int(movef)
elif move == "4":
movef = random.choice("046")
moveg = int(movef)
elif move == "5":
movef = random.choice("1357")
moveg = int(movef)
elif move == "6":
movef = random.choice("248")
moveg = int(movef)
elif move == "7":
movef = random.choice("37")
moveg = int(movef)
elif move == "8":
movef = random.choice("468")
moveg = int(movef)
elif move == "9":
movef = random.choice("57")
moveg = int(movef)
moves = [(move, evaluateMove(moveg)) for move in board.getValidMoves()]
random.shuffle(moves)
board.makeMove(moves[-1][0], player)
def game():
# The game function.
b = Board()
turn = 1
while True:
print("Turn: %i" % turn)
humanPlayer(b, Player_O)
if b.gameOver():
break
computerPlayer(b, Player_X)
if b.gameOver():
break
turn += 1
b.output()
if b.winner():
wina = 'Player "%s" wins' % b.winner()
if wina == 'Player "O" wins':
print("You have won, human. For now, I bid you farewell!")
else:
print("HA! I have won, inferior being! Come back when you are less carbon-based!")
else:
print('Game over')
if __name__ == "__main__":
game()
GameLoop()
GameLoop()