Tic-Tac-Toe AI Strategy

Tic-Tac-Toe Python AI (2)

*Remember: all code for this Tic-Tac-Toe AI can be found here*

Now that we have created an environment for our Tic-Tac-Toe game let’s create a simple two-player version of the game.

Multiplayer Tic-Tac-Toe

Again, let’s plan our code before we start:

  • We need a function called play that will deal with who plays when as well as print out all the information concerning the game
  • We also need a function called player_move which will get the current player to play on a certain square.

Before starting to code these functions, let’s ask ourselves what happens when we play Tic-Tac-Toe.

  1. First of all, before we even start the game we create (draw) a board
  2. We then decide who is going to play: Joseph and Eliott
  3. We decide who is going to play first: Joseph
  4. Now  Joseph decides where to play
  5. Joseph then plays where he decided and draws on that square
  6. Now we change turn and it becomes Eliott’s turn
  7. Now Eliott decides where to play
  8. He plays where he decided and draws on that square
  9. Now we change turn and it become’s Eliott’s turn
  10. Now Joseph decides where to play

Wait, line number 10 looks a lot like line number 4! Let’s try doing line number 5 now. Surprise! It works! We can do the same for lines number 6 through 9.

Time to code! (just a bit)

Now that we have a plan for how to play Tic-Tac-Toe let’s create a new file called tic-tac-toe.py and add the following code:

def play():
    """ Play Tic-Tac-Toe"""
    board = Board()
    board.output()
    player1 = input("What is X called? ")
    player2 = input("What is O called? ")
    print('{} is X and {} is O'.format(player1,player2))
    player = None
    while player not in ['X','O']:
         player = input('Who goes first(X or O)? ').capitalize()

    while not board.leaf():
        if player == 'X':
            move = player_move(board, '{}\'s turn'.format(player1))
            board.move(move, player)
        else:
            move = player_move(board, '{}\'s turn'.format(player2))
            board.move(move, player)
        board.output()
        player = get_opponent(player)

    if board.X_won():
        print("{} won!".format(player1))
    elif board.O_won():
        print("{} won!".format(player2))
    else:
        print("It's a tie!")

That’s the play method but what about the player_move method? That’s just a two step method:

  1. Ask the player where to play
  2. If it isn’t a valid move go back to step 1

And here’s the code that does just that:

def player_move(board, text):
    """ Get a player's move"""
    print('\n-------')
    print(text)
    move = None
    while move not in board.legal_moves():
        move = int(input('Select square to play at: '))-1
    return move

Now let’s import environment.py at the top of tic-tac-toe.py

from environment import *

And add this at the bottom:

if __name__ == '__main__':
play()

This calls the play function only if the file is being run directly and not being imported.

Here’s the complete code for tic-tac-toe.py.

Time for some (basic) AI!

Let’s plan how our AI will work:

  1. It will check if it can win if so it will play there
  2. It will check if the opponent can win if so it will play there
  3. It will play in the first square available from a list of “good moves”

Very easy! Here’s the code to implement this:

def computer_move(board, computer):
    """ Get the stupod computer's move """
    board = deepcopy(board) # Copy board as we will be changing it
    best_moves = [0,2,6,8,4,1,3,5,7]
    player = get_opponent(computer)

    # If computer can win: play there
    for move in board.legal_moves():
        board.move(move, computer)
        if board.winner() == computer:
            print('Computer will play at square: {}'.format(move+1))
            return move
        # Undo the move
        board.move(move, ' ')
        
    # If player can win: block the move
    for move in board.legal_moves():
        board.move(move, player)
        if board.winner() == player:
            print('Computer will play at square: {}'.format(move+1))
            return move
        # Undo the move
        board.move(move, ' ')

    # Else pick the best empty square
    for move in best_moves:
        if move in board.legal_moves():
            print('Computer will play at square: {}'.format(move+1))
            return move

And the new play function called computer_play is practically the same:

def computer_play():
    """ Play Tic-Tac-Toe against a (stupid) computer"""
    board = Board()
    board.output()
    player1 = input("What are you called? ")
    player2 = "Computer"
    print('{} is X and {} is O'.format(player1,player2))
    player = None
    while player not in ['X','O']:
         player = input('Who goes first?(X or O) ').capitalize()

    while not board.leaf():
        if player == 'X':
            move = player_move(board, '{}\'s turn'.format(player1))
            board.move(move, player)
        else:
            move = computer_move(board, player)
            board.move(move, player)
        board.output()
        player = get_opponent(player)

    if board.X_won():
        print("{} won!".format(player1))
    elif board.O_won():
        print("{} won!".format(player2))
    else:
        print("It's a tie!")

There you have it! A super simple AI! Of course, it’s far from perfect so we’ll make it unbeatable in the next tutorial!

What now?

Sign up to our email list to get notified when I post part 3 of this tutorial!

[sp-form formid=377]

 

Part 1

Part 3

2 Comments

Leave a Reply