Python Forum
tic tac toe python minimax alpha beta
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
tic tac toe python minimax alpha beta
#7
I played some games and the code appears to work just fine. One thing you might want to consider is returning a higher score for wins that occur in fewer moves. Your minimax code scores every win as 1 regardless of how many moves it takes to win. While I was playing the minmax algorithm occasionally passed on moves that would win immediately, picking other moves that were still guaranteed wins, but for the next move.

Below is a minimax algorithm that gives higher scores for wins that occur sooner. In addition to giving more weight to moves that win faster, I changed the board from a 2D list to a flat list. Just because a tic-tac-toe board has rows and columns is no reason why the software has to save the board in a 2D container. Iterating and indexing are easier with a flat list. Making a new board is easier with a flat list. Checking for wins is even easier with a flat list. The only time the software has to know about rows and columns is when it draws X's and O's on the board, and when the user clicks on the board to place their mark. In both cases additional transformations are required to get to/from turtle coordinates.
import turtle
import random

wins = ((0, 1, 2), (3, 4, 5), (6, 7, 8), (0, 3, 6), (1, 4, 7), (2, 5, 8), (0, 4, 8), (2, 4, 6))
board = [''] * 9
ROBOT = 'X'
HUMAN = 'O'
DRAW = 2


def line(start, end):
    """Draw a line from start to end."""
    turtle.up()
    turtle.goto(*start)
    turtle.down()
    turtle.goto(*end)


def draw_marker(square, marker):
    """Draw an x or o."""
    x = square % 3 + 0.5
    y = square // 3 + 0.5
    if marker == ROBOT:
        turtle.color('blue')
        line((x-0.4, y-0.4), (x+0.4, y+0.4))
        line((x-0.4, y+0.4), (x+0.4, y-0.4))
    elif marker == HUMAN:
        turtle.color('red')
        turtle.up()
        turtle.goto(x, y-0.4)
        turtle.seth(0)
        turtle.down()
        turtle.circle(0.4, steps=100)


def draw():
    """Draw the board."""
    turtle.pencolor('green')
    turtle.pensize(10)
    line((0, 1), (3, 1))
    line((0, 2), (3, 2))
    line((1, 0), (1, 3))
    line((2, 0), (2, 3))
    for square, marker in enumerate(board):
        draw_marker(square, marker)
    screen.update()


def game_over():
    """Return marker if marker won, 2 if draw, else 0."""
    for win in wins:
        a, b, c = [board[square] for square in win]
        if a and a == b == c:
            return a
    if '' not in board:
        return DRAW
    return 0


def open_squares():
    """Return list of squares that are open."""
    squares = [index for index, player in enumerate(board) if not player]
    random.shuffle(squares)  # Shuffle to make robot player less predictable.
    return squares


def minmax(marker=ROBOT, alpha=-11, beta=11, weight=10):
    """Use min-max algorithm to pick best move for robot player."""
    if (winner := game_over()) == ROBOT:
        return weight, None
    elif winner == HUMAN:
        return -weight, None
    elif winner == DRAW:
        return 0, None
    
    if marker == ROBOT:
        best = -weight, None
        other = HUMAN
    else:
        best = weight, None
        other = ROBOT

    for square in open_squares():
        board[square] = marker
        score, _ = minmax(other, alpha, beta, weight-1)
        board[square] = ""

        if score > best[0] and marker == ROBOT:
            best = score, square
            alpha = max(alpha, score)
        elif score < best[0] and marker == HUMAN:
            best = score, square
            beta = min(beta, score)
        if alpha >= beta:
                break
    return best


def play(square, marker):
    """Place marker in square.  Return game_over status."""
    board[square] = marker
    draw()
    return game_over()


def click(x, y):
    """Respond to mouse click.

    If player clicked on open square, place o marker and have robot play x.
    Display message if game over.
    """
    square = None
    if 0 <= x < 3 and 0 <= y < 3:
        square = int(x) + int(y) * 3
    if square is None or board[square]:
        return

    winner = play(square, HUMAN)
    if not winner:
        winner = play(minmax()[1], ROBOT)

    if winner:
        """Display results if game over."""
        if winner == DRAW:
            screen.textinput("Game over!", "Tie!")
        else:
            screen.textinput("Game over!", f"{winner} won!")
        turtle.bye()


screen = turtle.Screen()
screen.title("Tic Tac Toe ")
screen.setup(800, 800)
screen.setworldcoordinates(-0.2, 3.2, 3.2, -0.2)
screen.tracer(0, 0)
turtle.hideturtle()
screen.onclick(click)

# Robot makes first move.
play(minmax()[1], ROBOT)
screen.mainloop()
Reply


Messages In This Thread
tic tac toe python minimax alpha beta - by FSNWRMH - Nov-28-2023, 08:08 AM
RE: tic tac toe python minimax alpha beta - by deanhystad - Dec-19-2023, 06:40 PM

Possibly Related Threads…
Thread Author Replies Views Last Post
  Problem with a minimax algorith in Tic,Tac,Toe Daniel_Gargallo 5 2,057 Jan-27-2022, 07:23 PM
Last Post: deanhystad

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020