Tic-tac-toe, Human vs Machine (AI)
Tags: python, programming, ai, gamedev
Published: 2023-03-11 07:23:49


Ultimate challenge of human intelligence against artificial intelligence! 

Today, we will witness a battle of wits between a human and an `AI opponent` in one of the simplest yet most beloved games of all time: Tic-Tac-Toe.

!['tic-tac-toe-image'](https://i.ytimg.com/vi/w5Oftm3l2uQ/maxresdefault.jpg)

<br/>

## Tic-tac-toe and AI

Tic-Tac-Toe is a classic game that has been played by generations of children and adults alike. It's a game that is easy to learn, but difficult to master. 

However, with the advent of AI (Artificial Intelligence), even the most skilled human players may find themselves struggling to keep up with their electronic counterparts.

<br/>


_It's important to first gain experience by coding the game to play against a human opponent._

__Related Article__: [Tic-tac-toe, Human vs Human](https://speakpython.codes/two-player-game/2023/03/01/tic-tac-toe-human-vs-human.html).  



<br/>

> Keep calm coding begins....

## Tic-tac-toe in Python
<br/>

### Grid box pattern 

The `game_grid(value)` function takes a list value containing the current state of the Tic-Tac-Toe game board as input.

```python
def game_grid(value):  
    print("\n")  
    print("\t____________________")  
    print("\t|      |      |     |")  
    print("\t|    {} |  {}   |  {}  |".format(value[0], value[1], value[2]))  
    print('\t|______|______|_____|')  
    print("\t|      |      |     |") 
    print("\t|   {}  |  {}   |  {}  |".format(value[3], value[4], value[5]))  
    print('\t|______|______|_____|')  
    print("\t|      |      |     |")  
    print("\t|  {}   |  {}   |  {}  |".format(value[6], value[7], value[8]))  
    print('\t|______|______|_____|')
    print("\n") 
```

<br/>

### Possible winning patterns
The code defines a list called `wining_pattern` which contains sub-lists of all the possible winning combinations in a Tic-Tac-Toe game. 

```python
wining_pattern = [
    
    [1,2,3],
    [4,5,6],
    [7,8,9],
    [1,4,7],
    [2,5,8],
    [3,6,9],
    [1,5,9],
    [3,5,7]
    
]
```
<br/>

### Variables initialisation

These variables are used to keep track of the state of the game, including which positions on the board have been taken and by whom.

```python
taken_moves = []
default_values = [' ' for i in range(9)]
players_moves = {
    'X_moves': [],
    'O_moves': []
}
players = ['X', 'O']
```

<br/>

### Update Game state 

The `update_game` function updates the game state based on the player's move and returns a visual representation of the updated game board.

```python
def update_game(move, player):
    taken_moves.append(move)
    players_moves[player + '_moves'].append(move)
    default_values[move - 1] = player
    return game_grid(default_values)
```

<br/>

### Decide winner 
On the basis of taken steps, recorded inside `players_moves` dictionary, `check_wining` will decide the winner.

```python
def check_wining(moves):
    for i in wining_pattern:
        if all(j in moves for j in i):
            return True 
    return False 
```

<br/>

## How machine will play

<br/>

### AI First move
The `initial_move()` used to determine the first move made by the machine when playing tic-tac-toe against a human player.

```python
def initial_move():
    #Acquire Center
    if 5 not in players_moves['X_moves']:
        return 5
    #Acquire any corner
    return random.choice([1,3,7,9])
```

<br/>

### AI Smart move 🤓

The `smart_move()` tries to find the best possible move for the player by analyzing the current state of the game and searching for potential winning slots.

```python
def smart_move(mine_move, opp_moves):
    next_move = []
    for i in winning_pattern:
        if not [x for x in mine_move if x in i]:
            for j in i:
                if j not in opp_moves:
                    next_move.append(j)
            if len(next_move) == 1:
                return next_move[0]
            next_move = []
    return False
```


<br />

### AI Winning move 🏆
The `winning_move()` checks if there is a possible winning move for the player and returns that move if there is, otherwise returns `None`.

```python
def winning_move():
    moves = smart_move(players_moves['X_moves'], players_moves['O_moves'])
    return moves if moves else None
```

<br />

### AI Random Edge move
The `random_edge_move()` returns the first available edge slot on the board, _starting from the top-left and moving clockwise_, if there is one.

```python
def random_edge_move():
    for i in [2,4,6,8]:   
        if i not in taken_moves:
            return i
```

<br />

## Driver Code - AI vs Human 
It plays a game between a human player (__X__) and the computer (__O__), using a combination of [_pre-defined strategies and randomness_](#ai-strategies) to determine the computer's moves.

```python
step = 0
game_grid(default_values)
while step < 9 and step >= 0:

    if step >= 4:
        print('Match tied!')
        break
    
    player = "X"
    try:
        move = int(input(player + " : "))
        if move < 10 and move not in taken_moves:
            step += 1
            update_game(move,player)
            winner = check_winning() if step > 1 else None
            if winner:
                print(winner, 'Won!')
                break
            elif step == 1:
                O_move = initial_move()
            else:
                O_move = winning_move()
                O_move = smart_move(players_moves['O_moves'], players_moves['X_moves']) if not O_move else O_move
                O_move = random_edge_move() if not O_move else O_move
            print("O (Python 🐍): ",O_move)
            player = "O"
            update_game(O_move, player)
            winner = check_winning() if step > 1 else None
            if winner:
                print(winner, 'Won!')
                break
            continue
        print("Invalid move! - either your move is too high or already taken.")
    except:
        print("Invalid move! - wrong input.")
```

<br />

### Example testing

- __X__ = Human Player
- __O__ = AI (Computer)

!['tic-tac-toe-ai-code-output'](https://speakpython.codes/artificial-intelligence/image/tic-tac-toe-ai-code-output.png)

<br />

> I understand it's difficult at once, to understand the code, please refers: [speakpython.codes/tic-tac-toe-human-vs-machine](https://speakpython.codes/artificial-intelligence/2023/03/09/tic-tac-toe-human-vs-machine.html) - for complete explanation.

---
_This article is contributed by [speakpython.codes](https://speakpython.codes)_