Python 3.2 Artificial Intelligence Tic-Tac-Toe

I came up with a simple AI for Tic-Tac-Toe, which is to make the computer opponent try to block my moves. Running the code throws no errors and the computer usually blocks me. However, it sometimes moves to a random location on the board. Also, some parts 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()

      

+3


source to share





All Articles