Skip to content

Minimax module

Provide functions with basic AI for computer moves.

This module allows more complexity to the computer moves using different kind of algorithms.

Examples:

>>> from tic_tac_toe.logic.minimax import minimax
>>> from tic_tac_toe.logic.models import GameState, Grid, Mark
>>> def preview(cells):
        print(cells[:3], cells[3:6], cells[6:], sep='\n')
>>> game_state = GameState(Grid("XXO O X O"), starting_mark=Mark('X'))
>>> for move in game_state.possible_moves:
        print("Score:", minimax(move, maximizer=Mark('X')))
        preview(move.after_state.grid.cells)
        print('-' * 10)

The module contains the following functions: - find_best_move(game_state: GameState) - Return the best move available. - minimax( move: Move, maximizer: Mark, choose_highest_score: bool = False ) - Return 1, 0 or -1 base in the result of the next move.

find_best_move(game_state)

Return the best move available.

Parameters:

Name Type Description Default
game_state GameState

current GameState, consisting of a current Grid (9 elemets that that can be X, O or spaces) and a starting Mark (default X)

required

Returns:

Type Description
Move | None

Move | None: Inmutable data Class that is strictly a data transfer object (DTO) whose main

purpose is to carry data. Consists of the mark identifying the player who made a move, a numeric zero-based index in the string of cells, and the two states before and after making a move.

Source code in src\backend\logic\minimax.py
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
def find_best_move(game_state: GameState) -> Move | None:
    """Return the best move available.

    Args:
        game_state (GameState): current GameState, consisting of a current Grid (9 elemets that
            that can be X, O or spaces) and a starting Mark (default X)

    Returns:
        Move | None: Inmutable data Class that is strictly a data transfer object (DTO) whose main
    purpose is to carry data. Consists of the mark identifying the player who made a move, a numeric
    zero-based index in the string of cells, and the two states before and after making a move.
    """
    maximizer: Mark = game_state.current_mark
    bound_minimax = partial(minimax, maximizer=maximizer)
    return max(game_state.possible_moves, key=bound_minimax)

minimax(move, maximizer, choose_highest_score=False)

Return 1, 0 or -1 base in the result of the next move.

Parameters:

Name Type Description Default
move Move

Inmutable data Class that is strictly a data transfer object (DTO) whose main purpose is to carry data. Consists of the mark identifying the player who made a move, a numeric zero-based index in the string of cells, and the two states before and after making a move.

required
maximizer Mark

Mark for the player

required
choose_highest_score bool

Defaults to False.

False

Returns:

Name Type Description
int int

returns 1, 0 or -1

Source code in src\backend\logic\minimax.py
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
def minimax(
    move: Move, maximizer: Mark, choose_highest_score: bool = False
) -> int:
    """Return 1, 0 or -1 base in the result of the next move.

    Args:
        move (Move): Inmutable data Class that is strictly a data transfer object (DTO) whose
            main purpose is to carry data. Consists of the mark identifying the player who made a
            move, a numeric zero-based index in the string of cells, and the two states before
            and after making a move.
        maximizer (Mark): Mark for the player
        choose_highest_score (bool, optional): Defaults to False.

    Returns:
        int: returns 1, 0 or -1
    """
    if move.after_state.game_over:
        return move.after_state.evaluate_score(maximizer)
    return (max if choose_highest_score else min)(
        minimax(next_move, maximizer, not choose_highest_score)
        for next_move in move.after_state.possible_moves
    )