Chapterبەش 6 · Lectureوانە 6.2

Minimax: An AI That Never LosesMinimax: یاریزانێکی ژیر کە هەرگیز نادۆڕێت

How a computer plays tic-tac-toe perfectly: scores for finished games, MAX and MIN players, the game tree, and the minimax algorithm in Python. Then three improvements: take a win when it is there (the course code missed it in 291 positions), difficulty levels with an evaluation function, and a score game that ends when the player wants.

کۆمپیوتەر چۆن بێ هەڵە یاری دەکات: بۆ یاریی کۆتاییهاتوو، یاریزانەکانی MAX و MIN، و ئەلگۆریزمی بە . پاشان سێ باشترکردن: وەرگرتنی بردنەوە کاتێک بەردەستە (کۆدی کۆرسەکە لە ⁦291⁩ شوێندا لەدەستی دا)، ئاستەکانی قورسی بە و یارییەکی کە کاتێک یاریزان بیەوێت کۆتایی دێت.

22 min read20 خولەک خوێندنەوە · 15 stepsهەنگاو

What you will learnچی فێر دەبیت

  • Explain scores, MAX and MIN, and how values move up a game tree.
  • Read and run the minimax tic-tac-toe AI, including recursion and undoing moves.
  • Fix the AI so that it always takes an immediate win (depth-aware scores).
  • Build difficulty levels with a depth limit and an evaluation function, and a validated score game.
  • ، MAX و MIN ڕوون بکەیتەوە و بەهاکان چۆن بە سەردەکەون.
  • بە بخوێنیتەوە و کاری پێ بکەیت، لەوانە و گەڕاندنەوەی جووڵەکان.
  • چاک بکەیت تاکو هەمیشە بردنەوەی دەستبەجێ وەربگرێت ( بەپێی ).
  • ئاستەکانی قورسی بە و دروست بکەیت، لەگەڵ یارییەکی کە پشتڕاست دەکاتەوە.

Two algorithms for the best moveدوو ئەلگۆریزم بۆ باشترین جووڵە

Two algorithms, and , are used in computers to make the best move in a game such as tic-tac-toe. This lesson is about minimax; alpha-beta pruning, its faster form, is the next lesson.

دوو ئەلگۆریزم هەن بە ناوی و کە لە کۆمپیوتەردا بەکار دەهێنرێن بۆ ئەنجامدانی باشترین جووڵە لە یارییەکی وەک . ئەم وانەیە دەربارەی ؛ ، کە شێوە خێراترەکەیەتی، وانەی داهاتوویە.

In Southern Kurdish the game is known as «یاریی ئێکس و وای»; the course article calls it «یاریی ئێکس‌وئۆ».

لە کوردیی باشووردا ئەم یارییە بە «یاریی ئێکس و وای» ناسراوە؛ وتارەکەی کۆرسەکە پێی دەڵێت «».

Playing against a friendیاریکردن لەگەڵ هاوڕێیەک

Imagine that you play tic-tac-toe with a friend. You want to win, and your friend tries to win too. If we want the computer to play instead of your friend, we need one of these two algorithms. The computer tries to make the best move when its turn comes, just as you try to make the best move when your turn comes.

بیهێنە بەرچاوی خۆت کە دەتەوێت لەگەڵ هاوڕێکەتدا بکەیت؛ تۆ دەتەوێت بیبەیتەوە و ئەویش هەوڵی بردنەوە دەدات. ئەگەر بمانەوێت لەبری هاوڕێکەت کۆمپیوتەرەکەت بەکار بهێنین، ئەوا پێویستمان بە یەکێک لەم دوو ئەلگۆریزمە دەبێت. کۆمپیوتەر هەوڵ دەدات کاتێک نۆرەی دێت باشترین جووڵە بکات، بە هەمان شێوە تۆش دەتەوێت کاتێک نۆرەت دێت باشترین جووڵە بکەیت.

Where the analogy stops workingسنووری ئەم نموونەیە

Your friend may make mistakes. Minimax assumes that the opponent always plays perfectly; against a weak player it still plays safely, but it does not set traps that only a weak player would fall into.

هاوڕێکەت دەکرێت هەڵە بکات. وا دادەنێت کە بەرامبەرەکەی هەمیشە بێ هەڵە یاری دەکات؛ بەرامبەر یاریزانێکی لاواز هێشتا بە سەلامەتی یاری دەکات، بەڵام ئەو داوانە دانانێتەوە کە تەنیا یاریزانێکی لاواز تێیان دەکەوێت.

This kind of search is called : the algorithm faces an opponent who wants the opposite result. Tic-tac-toe is a : what is good for one player is exactly as bad for the other.

ئەم جۆرە گەڕانە پێی دەوترێت : ئەلگۆریزمەکە ڕووبەڕووی بەرامبەرێک دەبێتەوە کە ئەنجامی پێچەوانەی دەوێت. : ئەوەی بۆ یاریزانێک باشە، ڕێک بە هەمان ئەندازە بۆ ئەوی تر خراپە.

Quick checkپشکنینی خێراWhy is tic-tac-toe called a zero-sum game?بۆچی بە دەوترێت ؟

Scores: how the computer judges a moveنمرەکان: کۆمپیوتەر چۆن جووڵەیەک هەڵدەسەنگێنێت

The computer chooses its moves by a score. A move that leads to its win gets a high score; a move that leads to its loss gets a lower score.

کۆمپیوتەر جووڵەکانی بەپێی هەڵدەبژێرێت (لە ئینگلیزیدا: score). ئەگەر جووڵەیەک بەرەو بردنەوەی ببات، بەرزی پێ دەدرێت؛ ئەگەریش جووڵەیەک بەرەو دۆڕانی ببات، نزمتری پێ دەدرێت.

For a finished game (a ) the score is simple. The course's function evaluate_board returns 1 if x has won, −1 if o has won and 0 otherwise, which here means a draw. This number is the of the end position.

بۆ یارییەکی کۆتاییهاتوو () سادەیە. کۆرسەکە evaluate_board 1 دەگەڕێنێتەوە ئەگەر x بردبێتیەوە، ⁦−1⁩ ئەگەر o بردبێتیەوە و 0 ئەگینا، کە لێرەدا واتە یەکسان. ئەم ژمارەیە شوێنی کۆتاییە.

The score of a finished gameنمرەی یارییەکی کۆتاییهاتووscores_demo.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
# The score of a FINISHED game. Save next to tic_tac_toe.py.
from tic_tac_toe import player_won


def evaluate_board(board):
    if player_won(board, 'x'):
        return 1                        # x (the AI) has won
    if player_won(board, 'o'):
        return -1                       # o (the human) has won
    return 0                            # a draw


x_wins = [['x', 'x', 'x'],
          ['o', 'o', ' '],
          [' ', ' ', ' ']]
o_wins = [['x', 'x', 'o'],
          [' ', 'o', ' '],
          ['o', 'x', ' ']]
a_draw = [['x', 'o', 'x'],
          ['x', 'o', 'o'],
          ['o', 'x', 'x']]
print(evaluate_board(x_wins), evaluate_board(o_wins), evaluate_board(a_draw))
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 3

Reuse player_won from the tic-tac-toe lesson: save this file next to tic_tac_toe.py.

player_won لە وانەی دووبارە بەکار بهێنەرەوە: ئەم لە تەنیشت tic_tac_toe.py پاشەکەوت بکە.

Lineدێڕی 6-12

+1 for an x win, −1 for an o win, 0 for a draw.

⁦+1⁩ بۆ بردنەوەی x، ⁦−1⁩ بۆ بردنەوەی o، 0 بۆ یەکسان.

Quick checkپشکنینی خێراA game ends with three o's in a column. What does evaluate_board return?یارییەک بە سێ o لە ستوونێکدا کۆتایی دێت. evaluate_board چی دەگەڕێنێتەوە؟

MAX and MIN: where the name comes fromMAX و MIN: ناوەکە لە کوێوە هاتووە

One player (the computer) wants to raise its chance of winning — to maximize the score. The other player (you) wants to lower the computer's chance — to minimize the score. That is why the method is called Minimax.

یاریزانێک (کۆمپیوتەرەکە) دەیەوێت هەلی بردنەوەی خۆی بەرز بکاتەوە، واتە Maximizeی بکات ( زۆرترین بکات). یاریزانەکەی تر (تۆ) دەتەوێت هەلی بردنەوەی کۆمپیوتەر نزم بکاتەوە، واتە Minimizeی بکەیت. بۆیە ئەم ڕێگەیە ناوی نراوە Minimax.

Playerیاریزان
In our programلە بەرنامەکەمانداthe AI, playing 'x'، بە 'x' یاری دەکاتthe human, playing 'o'مرۆڤ، بە 'o' یاری دەکات
Wants the score to beدەیەوێت ببێتas high as possible (+1)تا دەکرێت بەرز ⁦(+1)⁩as low as possible (−1)تا دەکرێت نزم ⁦(−1)⁩
In the codeلە کۆدەکەداis_maximizing_player = Trueis_maximizing_player = Trueis_maximizing_player = Falseis_maximizing_player = False
Quick checkپشکنینی خێراIn our program, which player is MAX?لە بەرنامەکەماندا کام یاریزان MAX ـە؟

The game treeداری یاری

To choose a move, minimax imagines the future as a . Each node is a board position, each branch is a move, and the levels take turns: MAX (x moves), MIN (o moves), MAX, … The leaves are finished games with their scores. Minimax then works from the bottom up: a MIN node takes the smallest value of its children (o picks the move that is worst for x), and a MAX node takes the largest.

بۆ هەڵبژاردنی جووڵەیەک، داهاتوو وەک وێنا دەکات. هەر شوێنێکی تەختەیە، هەر لقێک جووڵەیەکە و ئاستەکان نۆرە دەگرن: ⁦MAX (x⁩ دەجووڵێت)، ⁦MIN (o⁩ دەجووڵێت)، MAX، … یاریی کۆتاییهاتوون لەگەڵ . پاشان لە خوارەوە بۆ سەرەوە کار دەکات: MIN بچووکترین بەهای منداڵەکانی وەردەگرێت (o ئەو جووڵەیە هەڵدەبژێرێت کە بۆ x خراپترینە) و MAX گەورەترین.

A game tree that starts from a tic-tac-toe position where x is to move and three cells are empty. The levels are labelled MAX: x moves, MIN: o moves, MAX: x moves, and game over. x has three moves. Move 0 0 leads to a MIN node with value +1, marked “wins later”: whatever o plays (0 1 or 2 2), x then wins with its last move. Move 0 1 wins at once, value +1, marked “wins now”. Move 2 2 leads to a MIN node with value −1, marked “o can win”: o plays 0 0 and wins (−1), although o 0 1 would let x win (+1). The root takes the maximum: +1.داری یاری کە لە شوێنێکی یاریی ئێکس‌وئۆوە دەست پێدەکات کە نۆرەی x ـە و سێ خانە بەتاڵن. ئاستەکان ناونراون: MAX: نۆرەی x، MIN: نۆرەی o، MAX: نۆرەی x و یاری کۆتایی هات. x سێ جووڵەی هەیە. جووڵەی 0 0 دەگاتە نۆدێکی MIN بە بەهای +1، بە نیشانەی «دواتر دەباتەوە»: o هەر چییەک بکات (0 1 یان 2 2)، x بە دوایین جووڵەی دەیباتەوە. جووڵەی 0 1 دەستبەجێ دەیباتەوە، بەهای +1، بە نیشانەی «ئێستا دەباتەوە». جووڵەی 2 2 دەگاتە نۆدێکی MIN بە بەهای −1، بە نیشانەی «o دەتوانێت ببات»: o 0 0 دەکات و دەیباتەوە (−1)، ئەگەرچی o 0 1 ڕێگە دەدات x ببات (+1). نۆدی ڕەگەکە گەورەترین وەردەگرێت: +1.
A small, complete game tree. The values travel from the leaves up to the root. بچووک و تەواو. بەهاکان لە بۆ سەردەکەون.CêIT
  • Move 0 0: o can answer 0 1 or 2 2; both times x wins with its last move (+1). MIN takes min(+1, +1) = +1.
  • Move 0 1: x completes the middle column at once: +1.
  • Move 2 2: o can play 0 0 and complete the left column (−1). MIN takes min(−1, +1) = −1.
  • Root (MAX): max(+1, +1, −1) = +1. So x must avoid 2 2. Moves 0 0 and 0 1 look equally good — remember this tie.
  • جووڵەی ⁦0 0⁩: o دەتوانێت بە ⁦0 1⁩ یان ⁦2 2⁩ وەڵام بداتەوە؛ هەردوو جار x بە دوایین جووڵەی دەیباتەوە ⁦(+1). MIN min(+1, +1)⁩ = ⁦+1⁩ وەردەگرێت.
  • جووڵەی ⁦0 1⁩: x دەستبەجێ ستوونی ناوەڕاست تەواو دەکات: ⁦+1⁩.
  • جووڵەی ⁦2 2⁩: o دەتوانێت ⁦0 0⁩ بکات و ستوونی چەپ تەواو بکات ⁦(−1). MIN min(−1, +1)⁩ = ⁦−1⁩ وەردەگرێت.
  • ⁦(MAX)⁩: ⁦max(+1, +1, −1)⁩ = ⁦+1⁩. کەواتە x دەبێت خۆی لە ⁦2 2⁩ بپارێزێت. جووڵەکانی ⁦0 0⁩ و ⁦0 1⁩ وەک یەک باش دەردەکەون — ئەم یەکسانبوونە لە بیر بێت.

A full game from the empty board makes a much bigger tree: counting every path separately it has 549,946 positions, and 255,168 of them are finished games.

یارییەکی تەواو لە تەختەی بەتاڵەوە دارێکی زۆر گەورەتر دروست دەکات: ئەگەر هەموو ڕێگەیەک بە جیا بژمێردرێت، ⁦549,946⁩ شوێنی تێدایە و ⁦255,168⁩یان یاریی کۆتاییهاتوون.

Quick checkپشکنینی خێراA MIN node has three children with the values +1, 0 and +1. What is its value? MIN سێ منداڵی هەیە بە بەهاکانی ⁦+1⁩، 0 و ⁦+1⁩. بەهاکەی چەندە؟

Minimax in PythonMinimax بە Python

Now the course program, with the functions of the tic-tac-toe lesson imported from tic_tac_toe.py. It has three new parts: evaluate_board (the score), minimax (the search) and find_best_move (the AI's choice).

ئێستا کۆرسەکە، کە وانەی یاریی ئێکس‌وئۆ لە tic_tac_toe.pyەوە import دەکات. سێ بەشی نوێی هەیە: evaluate_board ()، minimax (گەڕانەکە) و find_best_move (هەڵبژاردنی ).

Tic-tac-toe against a minimax AI (first version)یاریی ئێکس‌وئۆ بەرامبەر کۆمپیوتەرێک کە Minimax بەکار دەهێنێت (یەکەم وەشان)minimax_ai.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
# First version, as in the course: every win scores +1 (improved later).
# The AI plays 'x' (the MAX player), the human plays 'o' (the MIN player).
# Save this file in the same folder as tic_tac_toe.py (previous lesson).
from tic_tac_toe import print_board, can_insert, player_won, draw, read_move


def evaluate_board(board):
    if player_won(board, 'x'):
        return 1                        # x (the AI) has won
    if player_won(board, 'o'):
        return -1                       # o (the human) has won
    return 0                            # a draw


count = [0]                             # how many positions minimax visited


def minimax(board, is_maximizing_player):
    count[0] += 1
    if player_won(board, 'x') or player_won(board, 'o') or draw(board):
        return evaluate_board(board)    # the game is over: give its score

    if is_maximizing_player:            # x's turn: take the HIGHEST score
        best_score = -float('inf')
        for row in range(3):
            for col in range(3):
                if board[row][col] == ' ':
                    board[row][col] = 'x'               # try the move
                    score = minimax(board, False)       # o answers
                    board[row][col] = ' '               # undo the move
                    best_score = max(best_score, score)
        return best_score
    else:                               # o's turn: take the LOWEST score
        best_score = float('inf')
        for row in range(3):
            for col in range(3):
                if board[row][col] == ' ':
                    board[row][col] = 'o'
                    score = minimax(board, True)        # x answers
                    board[row][col] = ' '
                    best_score = min(best_score, score)
        return best_score


def find_best_move(board):
    best_move = None
    best_score = -float('inf')
    for row in range(3):
        for col in range(3):
            if board[row][col] == ' ':
                board[row][col] = 'x'
                score = minimax(board, False)
                board[row][col] = ' '
                if score > best_score:  # keeps the FIRST of equal scores
                    best_score = score
                    best_move = (row, col)
    return best_move


def main():
    board = [[' ', ' ', ' '] for _ in range(3)]
    player = 'x'                        # the AI starts
    while True:
        print_board(board)
        if player == 'x':
            count[0] = 0
            row, col = find_best_move(board)
            can_insert(board, row, col, 'x')
            print(f"AI plays {row} {col} (positions examined: {count[0]})")
        else:
            row, col = read_move(player)
            if not can_insert(board, row, col, player):
                print("Invalid move. Try again.")
                continue
        if player_won(board, player):
            print_board(board)
            print(f"Player {player} wins!")
            break
        if draw(board):
            print_board(board)
            print("It's a draw!")
            break
        player = 'o' if player == 'x' else 'x'


if __name__ == "__main__":
    main()
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 4

The board functions come from the previous lesson (import). The course file defines them again with other names: make_move, check_move, check_draw.

تەختەکە لە وانەی پێشووەوە دێن (import). کۆرسەکە دووبارە بە ناوی تر دەیانناسێنێت: make_move، check_move، check_draw.

Lineدێڕی 15

count is a one-item list, so the functions can change count[0] without global. It counts the positions minimax visits.

count بە یەک دانە، بۆیە دەتوانن count[0] بگۆڕن بەبێ global. ئەو شوێنانە دەژمێرێت کە سەردانیان دەکات.

Lineدێڕی 20-21

Stop when the game is over: return the score of this finished game (a leaf of the tree).

کاتێک یارییەکە کۆتایی هات بوەستە: ئەم یارییە کۆتاییهاتووە بگەڕێنەوە ( دارەکە).

Lineدێڕی 23-32

MAX: try 'x' in every empty cell, let MIN answer (minimax(board, False)), undo the move, keep the highest score. Starting from -float('inf') means “worse than anything”.

MAX: 'x' لە هەموو خانەیەکی بەتاڵدا تاقی بکەرەوە، با MIN وەڵام بداتەوە (minimax(board, False))، جووڵەکە بگەڕێنەوە، بەرزترین هەڵبگرە. دەستپێکردن لە -float('inf') واتە «لە هەموو شتێک خراپتر».

Lineدێڕی 29

: minimax calls itself for the position one move deeper.

: بانگی خۆی دەکاتەوە بۆ ئەو شوێنەی یەک جووڵە قووڵترە.

Lineدێڕی 33-42

MIN: the same with 'o', keeping the lowest score.

MIN: هەمان شت بە 'o'، بە هەڵگرتنی نزمترین .

Lineدێڕی 45-57

The AI tries each empty cell, scores it with minimax(board, False) and keeps the best. > keeps the FIRST of several equal scores.

هەموو خانەیەکی بەتاڵ تاقی دەکاتەوە، بە minimax(board, False) دەداتێ و باشترینیان هەڵدەگرێت. > یەکەمی چەند یەکسان هەڵدەگرێت.

Lineدێڕی 66-69

The counter is reset before every AI move and printed with a label after it.

پێش هەموو جووڵەیەکی سفر دەکرێتەوە و دوای جووڵەکە بە ناونیشانەوە چاپ دەکرێت.

Quick checkپشکنینی خێراWhy does minimax start MAX's best score at -float('inf')?بۆچی باشترین MAX لە -float('inf')ەوە دەست پێدەکات؟

12 Beginner Python Projects - Coding CoursefreeCodeCamp.org · Englishئینگلیزی · 5M viewsبینین · 125K likesلایک · Partبەشی 59:59–1:15:53 (ofلە 3:00:29)

Kylie Ying writes an unbeatable tic-tac-toe player in Python with a recursive minimax function that tries each move and then undoes it.

⁦Kylie Ying⁩ بە یاریزانێکی نەبەزیو بۆ دەنووسێت، بە کە بە کار دەکات: هەر جووڵەیەک تاقی دەکاتەوە و پاشان لایدەباتەوە.

Plays 59:59–1:15:53, chapter '7. Tic-Tac-Toe AI'. Her program is built with classes and a flat list of 9 cells, so the code looks different from ours, but the minimax steps are the same: try a move, call minimax for the other player, undo the move, keep the best score (starting from -math.inf / math.inf). Her score is bigger for a quicker win, the same idea as our 'take a win' fix.

لە ⁦59:59⁩ تا ⁦1:15:53⁩ لێدەدرێت، بەشی «⁦7. Tic-Tac-Toe AI⁩». ئەو بە و تەختی 9 خانەیی دروستکراوە، بۆیە کۆدەکەی لە هی ئێمە جیاوازە، بەڵام هەنگاوەکانی وەک یەکن: جووڵەیەک تاقی بکەرەوە، بۆ یاریزانەکەی تر بانگ بکە، جووڵەکە لابەرەوە، باشترین هەڵبگرە (بە -math.inf / math.inf دەست پێدەکات). ئەو بۆ بردنەوەی خێراتر گەورەترە؛ ئەمە هەمان بیرۆکەی شاشەی «چاککردن: کاتێک بردنەوە بەردەستە وەریبگرە»یە.

Minimax in PythonMinimax بە Python

Running the gameکارپێکردنی یارییەکە

The course tested the program with a human who always takes the first free cell of the list 1 1, 0 0, 0 1, 0 2, 1 0, 1 2, 2 0, 2 1, 2 2. Here is the same game (the human's moves are 1 1, 0 2, 1 0 and 2 1):

کۆرسەکە بە مرۆڤێک تاقی کردەوە کە هەمیشە یەکەم خانەی بەتاڵی ئەم لیستە دەگرێت: ⁦1 1⁩، ⁦0 0⁩، ⁦0 1⁩، ⁦0 2⁩، ⁦1 0⁩، ⁦1 2⁩، ⁦2 0⁩، ⁦2 1⁩، ⁦2 2⁩. ئەمە هەمان یارییە (جووڵەکانی مرۆڤەکە ⁦1 1⁩، ⁦0 2⁩، ⁦1 0⁩ و ⁦2 1⁩ن):

python3 minimax_ai.pyکارپێکردنی ⁦python3 minimax_ai.py⁩
    |    | 
---------------
    |    | 
---------------
    |    | 

AI plays 0 0 (positions examined: 549945)
x   |    | 
---------------
    |    | 
---------------
    |    | 

Player o, enter your move (row col): 1 1
x   |    | 
---------------
    |o   | 
---------------
    |    | 

AI plays 0 1 (positions examined: 7331)
x   |x   | 
---------------
    |o   | 
---------------
    |    | 

Player o, enter your move (row col): 0 2
x   |x   |o
---------------
    |o   | 
---------------
    |    | 

AI plays 2 0 (positions examined: 197)
x   |x   |o
---------------
    |o   | 
---------------
x   |    | 

Player o, enter your move (row col): 1 0
x   |x   |o
---------------
o   |o   | 
---------------
x   |    | 

AI plays 1 2 (positions examined: 13)
x   |x   |o
---------------
o   |o   |x
---------------
x   |    | 

Player o, enter your move (row col): 2 1
x   |x   |o
---------------
o   |o   |x
---------------
x   |o   | 

AI plays 2 2 (positions examined: 1)
x   |x   |o
---------------
o   |o   |x
---------------
x   |o   |x

It's a draw!
  • Before its first move the AI examines 549,945 positions: the whole game tree except the empty start board, which find_best_move handles itself. On a laptop this takes a few seconds (the course measured 4.3 s).
  • Each later move has fewer empty cells, so the tree shrinks fast: 7,331, then 197, 13 and 1.
  • The human plays reasonably and the game ends in a draw, like every game between two perfect players of tic-tac-toe.
  • پێش یەکەم جووڵەی ⁦549,945⁩ شوێن دەپشکنێت: هەموو جگە لە تەختە بەتاڵەکەی سەرەتا، کە find_best_move خۆی مامەڵەی لەگەڵ دەکات. لەسەر لاپتۆپێک ئەمە چەند چرکەیەک دەبات (کۆرسەکە ⁦4.3⁩ چرکەی پێوا).
  • هەر جووڵەیەکی دواتر خانەی بەتاڵی کەمترە، بۆیە دارەکە بە خێرایی بچووک دەبێتەوە: ⁦7,331⁩، پاشان ⁦197⁩، ⁦13⁩ و 1.
  • مرۆڤەکە بە باشی یاری دەکات و یارییەکە بە یەکسانی کۆتایی دێت، وەک هەموو یارییەکی لە نێوان دوو یاریزانی بێ هەڵەدا.

The course also checked all 2,423 positions where x is to move: this minimax and the alpha-beta version of the next lesson always choose the same move. Alpha-beta is only faster, never different.

کۆرسەکە هەموو ئەو ⁦2,423⁩ شوێنەشی پشکنی کە نۆرەی x ـە: ئەم و وەشانی وانەی داهاتوو هەمیشە هەمان جووڵە هەڵدەبژێرن. تەنیا خێراترە، هەرگیز جیاواز نییە.

Quick checkپشکنینی خێراWhy does the AI examine 549,945 positions before its first move but only 7,331 before its second?بۆچی پێش یەکەم جووڵەی ⁦549,945⁩ شوێن دەپشکنێت، بەڵام پێش دووەم جووڵەی تەنیا ⁦7,331⁩؟

Fix: take a win when it is thereچاککردن: کاتێک بردنەوە بەردەستە وەریبگرە

Look at the game tree again. Moves 0 0 (“wins later”) and 0 1 (“wins now”) both have the value +1, and find_best_move keeps the first of equal scores. So the AI plays 0 0 and wins two moves later, although it could win now. Every win scores +1, however far away it is.

دیسان سەیری بکە. جووڵەکانی ⁦0 0⁩ («دواتر دەباتەوە») و ⁦0 1⁩ («ئێستا دەباتەوە») هەردووکیان بەهای ⁦+1⁩یان هەیە و find_best_move یەکەمی یەکسان هەڵدەگرێت. بۆیە ⁦0 0⁩ دەکات و دوو جووڵە دواتر دەیباتەوە، ئەگەرچی دەیتوانی ئێستا ببات. هەموو بردنەوەیەک ⁦+1⁩ وەردەگرێت، هەرچەند دوور بێت.

Depth-aware scoresنمرەکان بەپێی قووڵاییimmediate_win.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
# Does the AI take a win that is available RIGHT NOW?
# Save next to tic_tac_toe.py and minimax_ai.py.
from tic_tac_toe import player_won, draw
from minimax_ai import minimax          # the old version: +1 / 0 / -1


def minimax_depth(board, depth, is_maximizing_player):
    """Like minimax, but a FASTER win scores higher."""
    if player_won(board, 'x'):
        return 10 - depth               # win at depth 1 -> 9, at depth 3 -> 7
    if player_won(board, 'o'):
        return depth - 10               # a later loss is less bad
    if draw(board):
        return 0
    scores = []
    for row in range(3):
        for col in range(3):
            if board[row][col] == ' ':
                board[row][col] = 'x' if is_maximizing_player else 'o'
                scores.append(minimax_depth(board, depth + 1,
                                            not is_maximizing_player))
                board[row][col] = ' '
    return max(scores) if is_maximizing_player else min(scores)


def find_best_move_depth(board):
    best_move, best_score = None, -float('inf')
    for row in range(3):
        for col in range(3):
            if board[row][col] == ' ':
                board[row][col] = 'x'
                score = minimax_depth(board, 1, False)  # x's move = depth 1
                board[row][col] = ' '
                if score > best_score:
                    best_move, best_score = (row, col), score
    return best_move


def show_scores(board):
    for row in range(3):
        for col in range(3):
            if board[row][col] == ' ':
                board[row][col] = 'x'
                old = minimax(board, False)
                new = minimax_depth(board, 1, False)
                board[row][col] = ' '
                print(f"  x at {row} {col}: old score {old:2}, new score {new:2}")
    print("  the new AI plays", find_best_move_depth(board))


if __name__ == "__main__":
    for rows in (["  x", "oxo", "ox "], ["   ", "  x", "oox"]):
        board = [list(r) for r in rows]
        print("board rows:", rows)
        show_scores(board)
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 9-12

A win found at depth 1 scores 9, at depth 3 only 7; an o win at depth 2 scores −8.

بردنەوەیەک لە 1دا 9 وەردەگرێت، لە 3دا تەنیا 7؛ بردنەوەی o لە 2دا ⁦−8⁩.

Lineدێڕی 15-23

The same search as before, written shorter: collect the children's scores, then take max or min.

هەمان گەڕانی پێشوو، بە کورتی نووسراوە: منداڵەکان کۆ بکەرەوە، پاشان max یان min وەربگرە.

Lineدێڕی 26-36

The new find_best_move_depth: x's own move counts as depth 1.

find_best_move_depthی نوێ: جووڵەی خودی x وەک 1 دەژمێردرێت.

Lineدێڕی 39-48

Print the old and the new score of every move, and the move the new AI chooses.

کۆن و نوێی هەموو جووڵەیەک چاپ بکە، لەگەڵ ئەو جووڵەیەی نوێ هەڵیدەبژێرێت.

Lineدێڕی 51-55

Two test boards: the position of the game tree, and the course's example.

دوو تەختەی تاقیکردنەوە: شوێنی و نموونەکەی کۆرسەکە.

With the new scores the immediate win (9) beats the slower win (7 or 5), and the losing move of the tree gets −8. The AI now plays 0 1 in the tree position and 0 2 in the course's example. From now on, every AI in this lesson uses these depth-aware scores: the hard level of the difficulty program (next screen) is this fixed minimax, ready to play against.

ئێستا بە بەپێی ، بردنەوەی دەستبەجێ ⁦(9)⁩ لە بردنەوەی خاوتر (⁦7⁩ یان ⁦5⁩) دەباتەوە و جووڵە دۆڕاوەکەی دارەکە ⁦−8⁩ وەردەگرێت. ئێستا لە شوێنی دارەکەدا ⁦0 1⁩ دەکات و لە نموونەکەی کۆرسەکەدا ⁦0 2⁩. لێرە بەدواوە هەموو یاریزانێکی کۆمپیوتەریی ئەم وانەیە بەپێی بەکار دەهێنێت: ئاستی hardی ئاستەکانی قورسی (پەڕەی داهاتوو) هەمان چاککراوە و دەتوانیت یاریی لەگەڵ بکەیت.

Quick checkپشکنینی خێراWith depth-aware scores, what does an x win on the AI's very next move score?بە بەپێی ، بردنەوەی x لە ڕێک جووڵەی داهاتووی چەند وەردەگرێت؟

Fix: take a win when it is thereچاککردن: کاتێک بردنەوە بەردەستە وەریبگرە

Extra: check every position, and a cleaner designزیادە: پشکنینی هەموو شوێنەکان و دیزاینێکی ڕێکتر

Difficulty levelsئاستەکانی قورسی

The course's “difficulty levels” program lets the player choose how strong the AI is:

«ئاستەکانی قورسی»ی کۆرسەکە ڕێگە دەدات یاریزانەکە هەڵبژێرێت چەند بەهێز بێت:

  • easy: a random free cell (random.choice).
  • medium: minimax that looks only 2 moves ahead (max_depth = 2).
  • hard: minimax to the end of the game (max_depth = float('inf')).
  • easy: خانەیەکی بەتاڵی هەڕەمەکی (random.choice).
  • medium: کە تەنیا 2 جووڵە بۆ پێشەوە دەڕوانێت (max_depth = 2).
  • hard: تا کۆتایی یارییەکە (max_depth = float('inf')).

For this, minimax gets two extra parameters, depth and max_depth, and it also stops when depth >= max_depth. main() asks “Choose difficulty (easy, medium, hard):”, builds the board and plays one game. In the course's test the random “easy” AI lost to the human, while “medium” and “hard” both drew against the same human moves as before.

بۆ ئەمە، دوو زیادە وەردەگرێت (depth و max_depth) و کاتێک depth >= max_depthیش بێت دەوەستێت. main() دەپرسێت «⁦Choose difficulty (easy, medium, hard)⁩:»، تەختەکە دروست دەکات و یەک یاری دەکات. لە تاقیکردنەوەکەی کۆرسەکەدا هەڕەمەکیی «easy» بەرامبەر مرۆڤەکە دۆڕا، بەڵام «medium» و «hard» هەردووکیان بەرامبەر هەمان جووڵەکانی پێشووی مرۆڤ یەکسان بوون.

Difficulty levels, correctedئاستەکانی قورسی، چاککراوdifficulty.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
# Three difficulty levels. Save next to tic_tac_toe.py.
import random
from tic_tac_toe import print_board, can_insert, player_won, draw, read_move

LINES = ([[(r, 0), (r, 1), (r, 2)] for r in range(3)] +          # rows
         [[(0, c), (1, c), (2, c)] for c in range(3)] +          # columns
         [[(0, 0), (1, 1), (2, 2)], [(0, 2), (1, 1), (2, 0)]])   # diagonals


def estimate(board):
    """Evaluation function: lines x can still complete minus lines o can."""
    x_open = sum(1 for line in LINES if all(board[r][c] != 'o' for r, c in line))
    o_open = sum(1 for line in LINES if all(board[r][c] != 'x' for r, c in line))
    return (x_open - o_open) / 10       # always between -1 and 1


def minimax(board, depth, is_maximizing, max_depth):
    if player_won(board, 'x'):
        return 10 - depth
    if player_won(board, 'o'):
        return depth - 10
    if draw(board):
        return 0
    if depth >= max_depth:              # not finished, but we stop looking
        return estimate(board)
    scores = []
    for row in range(3):
        for col in range(3):
            if board[row][col] == ' ':
                board[row][col] = 'x' if is_maximizing else 'o'
                scores.append(minimax(board, depth + 1, not is_maximizing,
                                      max_depth))
                board[row][col] = ' '
    return max(scores) if is_maximizing else min(scores)


def find_best_move(board, level):
    empty = [(r, c) for r in range(3) for c in range(3) if board[r][c] == ' ']
    if level == 'easy':
        return random.choice(empty)               # any free cell
    max_depth = 2 if level == 'medium' else 9     # medium: 2 moves ahead
    best_move, best_score = None, -float('inf')
    for row, col in empty:
        board[row][col] = 'x'
        score = minimax(board, 1, False, max_depth)
        board[row][col] = ' '
        if score > best_score:
            best_move, best_score = (row, col), score
    return best_move


def ask_level():
    while True:
        level = input("Choose difficulty (easy, medium, hard): ").strip().lower()
        if level in ('easy', 'medium', 'hard'):
            return level
        print("Please type easy, medium or hard.")


def main():
    level = ask_level()
    board = [[' ', ' ', ' '] for _ in range(3)]
    player = 'x'
    while True:
        print_board(board)
        if player == 'x':
            row, col = find_best_move(board, level)
            can_insert(board, row, col, 'x')
            print(f"AI ({level}) plays {row} {col}")
        else:
            row, col = read_move(player)
            if not can_insert(board, row, col, player):
                print("Invalid move. Try again.")
                continue
        if player_won(board, player):
            print_board(board)
            print(f"Player {player} wins!")
            break
        if draw(board):
            print_board(board)
            print("It's a draw!")
            break
        player = 'o' if player == 'x' else 'x'


if __name__ == "__main__":
    main()
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 5-7

The 8 winning lines as lists of cells.

8 هێڵە براوەکە وەک لە خانەکان.

Lineدێڕی 10-14

The evaluation function: lines that x can still complete, minus lines that o can still complete, divided by 10 so it stays between −1 and 1 (a real win is worth much more).

: ئەو هێڵانەی x هێشتا دەتوانێت تەواویان بکات، کەمکراو لەو هێڵانەی o هێشتا دەتوانێت، دابەشی ⁦10⁩ تاکو لە نێوان ⁦−1⁩ و 1دا بمێنێتەوە (بردنەوەیەکی ڕاستەقینە زۆر زیاتر دەهێنێت).

Lineدێڕی 18-23

Finished games: depth-aware scores, as in the previous screen.

یاریی کۆتاییهاتوو: بەپێی ، وەک پەڕەی پێشوو.

Lineدێڕی 24-25

Depth limit reached: estimate instead of pretending it is a draw.

گەیشتن بە : خەمڵاندن لەبری ئەوەی وا دابنێین یەکسانە.

Lineدێڕی 41

medium looks 2 moves ahead; hard looks 9, which is the whole game.

⁦medium 2⁩ جووڵە بۆ پێشەوە دەڕوانێت؛ ⁦hard 9⁩، کە هەموو یارییەکەیە.

Lineدێڕی 52-57

The level is validated: only easy, medium or hard is accepted.

ئاستەکە پشتڕاست دەکرێتەوە: تەنیا easy، medium یان hard وەردەگیرێت.

Notice what happened: the typo hrad was refused, and the medium AI took the centre first: the centre lies on 4 of the 8 winning lines (a corner on 3, an edge on 2), so the evaluation function scores it best. The human blocked every threat and the game ended in a draw.

سەرنج بدە چی ڕوویدا: هەڵە نووسینی hrad ڕەت کرایەوە و medium یەکەم جار ناوەڕاستی گرت: ناوەڕاست لەسەر 4 لە 8 هێڵە براوەکەیە (گۆشەیەک لەسەر 3 و لایەک لەسەر ⁦2⁩)، بۆیە باشترین پێ دەدات. مرۆڤەکە هەموو هەڕەشەیەکی ڕاگرت و یارییەکە بە یەکسانی کۆتایی هات.

Quick checkپشکنینی خێراIn the course's version, the player types hrad as the level. What happens?لە وەشانەکەی کۆرسەکەدا یاریزانەکە hrad وەک ئاست دەنووسێت. چی ڕوودەدات؟

Difficulty levelsئاستەکانی قورسی

Does the evaluation function help?ئایا کرداری هەڵسەنگاندن یارمەتی دەدات؟

Definitionپێناسە

A function f(n) that gives each node a score for choosing which node to expand next; in games, a function that estimates how good an unfinished position is.

⁦(f(n))⁩ کە نمرەیەک دەدات بە هەر نۆدێک بۆ هەڵبژاردنی ئەوەی کام نۆد دواتر فراوان بکرێت؛ لە یارییەکاندا، کردارێکە کە دەخەمڵێنێت پێگەیەکی تەواونەبوو چەند باشە.

Let the computer answer: this program lets the medium AI play first and tries every possible reply of the human, game after game. It runs once with unfinished boards scored 0 (as in the course) and once with the evaluation function.

با کۆمپیوتەرەکە وەڵام بداتەوە: ئەم ڕێگە دەدات medium یەکەم جار یاری بکات و هەموو وەڵامێکی ئەگەریی مرۆڤەکە تاقی دەکاتەوە، یاری لە دوای یاری. جارێک بە هەژمارکردنی تەختە تەواونەبووەکان بە 0 (وەک کۆرسەکە) و جارێک بە کار دەکات.

Medium against every possible humanmedium بەرامبەر هەموو مرۆڤێکی ئەگەریcompare_medium.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
# Can a human beat the "medium" AI? Try EVERY possible human reply.
# Save next to difficulty.py.
import difficulty


def count_results(board, results):
    """The AI (x) moves, then we try each possible reply of o."""
    row, col = difficulty.find_best_move(board, 'medium')
    board[row][col] = 'x'
    if difficulty.player_won(board, 'x'):
        results['AI wins'] += 1
    elif difficulty.draw(board):
        results['draw'] += 1
    else:
        for r in range(3):
            for c in range(3):
                if board[r][c] == ' ':
                    board[r][c] = 'o'
                    if difficulty.player_won(board, 'o'):
                        results['human wins'] += 1
                    elif difficulty.draw(board):
                        results['draw'] += 1
                    else:
                        count_results(board, results)
                    board[r][c] = ' '
    board[row][col] = ' '


for label, estimate in [("medium WITHOUT evaluation", lambda board: 0),
                        ("medium WITH evaluation", difficulty.estimate)]:
    difficulty.estimate = estimate      # swap the evaluation function
    results = {'AI wins': 0, 'draw': 0, 'human wins': 0}
    count_results([[' ', ' ', ' '] for _ in range(3)], results)
    print(label, results)
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 6-26

A recursive function: the AI moves, then every reply of o is tried, and the results are counted.

خۆبانگکەرەوە: دەجووڵێت، پاشان هەموو وەڵامێکی o تاقی دەکرێتەوە و ئەنجامەکان دەژمێردرێن.

Lineدێڕی 29-31

Swap the evaluation function: first one that always says 0, then the real one.

بگۆڕە: سەرەتا یەکێک کە هەمیشە دەڵێت 0، پاشان ڕاستەقینەکە.

Without an evaluation function a human can beat the medium AI in 9 different ways. With the evaluation function the same 2-move search never loses when it starts. A good estimate makes a short search much stronger — this is how real game programs, such as chess engines, work: they cannot search to the end, so they search a few moves deep and estimate.

بەبێ مرۆڤ دەتوانێت بە 9 ڕێگەی جیاواز medium ببات. بە ، هەمان گەڕانی 2 جووڵەیی هەرگیز نادۆڕێت کاتێک دەست پێدەکات. خەمڵاندنێکی باش گەڕانێکی کورت زۆر بەهێزتر دەکات — بەرنامە ڕاستەقینەکانی یاری، وەک بەرنامەکانی شەترەنج، بەم شێوەیە کار دەکەن: ناتوانن تا کۆتایی بگەڕێن، بۆیە چەند جووڵەیەک قووڵ دەگەڕێن و دەخەمڵێنن.

Quick checkپشکنینی خێراWhy does depth-limited minimax need an evaluation function?بۆچی بە پێویستی بە هەیە؟

Many games with a scoreچەند یارییەک لەگەڵ نمرە

The course's last version, “AI HUMAN TIC TOE SCORE”, plays game after game and keeps a score. It adds ai_score = 0, human_score = 0 and a function reset_board() that makes a new empty board (with global board).

دوایین وەشانی کۆرسەکە، «⁦AI HUMAN TIC TOE SCORE⁩»، یاری لە دوای یاری دەکات و هەڵدەگرێت. ai_score = 0، human_score = 0 و بە ناوی reset_board() زیاد دەکات کە تەختەیەکی بەتاڵی نوێ دروست دەکات (بە global board).

Its main() prints Score - AI: …, Human: … before every move. The human's input is inside try … except ValueError, which prints “Invalid input. Enter row and column numbers (0-2).” After a win the winner's score goes up by one and the board is reset; after a draw the board is reset too, and a new game begins. In the course's test the first game was a draw, then the AI won twice: Score - AI: 2, Human: 0.

main()ـەکەی پێش هەموو جووڵەیەک Score - AI: …, Human: … چاپ دەکات. مرۆڤەکە لە ناو try … except ValueErrorدایە، کە «⁦Invalid input. Enter row and column numbers (0-2)⁩.» چاپ دەکات. دوای بردنەوە براوەکە یەک زیاد دەکات و تەختەکە نوێ دەکرێتەوە؛ دوای یەکسانبوونیش تەختەکە نوێ دەکرێتەوە و یارییەکی نوێ دەست پێدەکات. لە تاقیکردنەوەی کۆرسەکەدا یاریی یەکەم یەکسان بوو، پاشان دوو جار بردییەوە: Score - AI: 2, Human: 0.

ExerciseڕاهێنانBuild a better score gameیارییەکی باشتری نمرە دروست بکە

Write score_game.py: the AI (with depth-aware scores) plays the human again and again and keeps the score. After each game it asks “Play again? (y/n)” (and accepts only y or n), the two sides take turns to start, and every move is read with read_move().

score_game.py بنووسە: (بە بەپێی ) جار لە دوای جار لەگەڵ مرۆڤەکەدا یاری دەکات و هەڵدەگرێت. دوای هەر یارییەک دەپرسێت «⁦Play again? (y/n)⁩» (و تەنیا y یان n وەردەگرێت)، دوو لایەنەکە نۆرە دەگرن بۆ دەستپێکردن و هەموو جووڵەیەک بە read_move() دەخوێنرێتەوە.

Hintئاماژە

Put one game into a function play_one_game(first_player) that returns 'x', 'o' or 'draw'.

یەک یاری بخە ناو بە ناوی play_one_game(first_player) کە 'x'، 'o' یان 'draw' بگەڕێنێتەوە.

Show answerوەڵامەکە پیشان بدە
score_game.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
# AI against human with a score, several games. Save next to tic_tac_toe.py
# and immediate_win.py.
from tic_tac_toe import print_board, can_insert, player_won, draw, read_move
from immediate_win import find_best_move_depth


def play_one_game(first_player):
    """Play one game and return 'x', 'o' or 'draw'."""
    board = [[' ', ' ', ' '] for _ in range(3)]
    player = first_player
    while True:
        print_board(board)
        if player == 'x':
            row, col = find_best_move_depth(board)
            can_insert(board, row, col, 'x')
            print(f"AI plays {row} {col}")
        else:
            row, col = read_move(player)
            if not can_insert(board, row, col, player):
                print("Invalid move. Try again.")
                continue
        if player_won(board, player):
            print_board(board)
            print(f"Player {player} wins!")
            return player
        if draw(board):
            print_board(board)
            print("It's a draw!")
            return 'draw'
        player = 'o' if player == 'x' else 'x'


def ask_play_again():
    while True:
        answer = input("Play again? (y/n): ").strip().lower()
        if answer in ('y', 'n'):
            return answer == 'y'
        print("Please type y or n.")


def main():
    ai_score = human_score = 0
    first = 'o'                         # the human starts the first game
    while True:
        print(f"Score - AI: {ai_score}, Human: {human_score}\n")
        result = play_one_game(first)
        if result == 'x':
            ai_score += 1
        elif result == 'o':
            human_score += 1
        if not ask_play_again():
            break
        first = 'x' if first == 'o' else 'o'    # take turns to start
    print(f"Final score - AI: {ai_score}, Human: {human_score}")


if __name__ == "__main__":
    main()
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 7-30

One game, from an empty board, starting with first_player; it returns the result instead of looping forever.

یەک یاری، لە تەختەیەکی بەتاڵەوە، کە بە first_player دەست پێدەکات؛ لەبری خولانەوەی هەتاهەتایی ئەنجامەکە دەگەڕێنێتەوە.

Lineدێڕی 33-38

Ask until the answer is y or n.

بپرسە تا وەڵامەکە y یان n دەبێت.

Lineدێڕی 51-53

Stop when the player says n; otherwise the other side starts the next game.

کاتێک یاریزان دەڵێت n بوەستە؛ ئەگینا لایەنەکەی تر یارییەکەی داهاتوو دەست پێدەکات.

No global variables are needed: the scores live in main(), and every game gets a fresh board inside play_one_game().

هیچ پێویست نییە: لە ناو main()دان و هەر یارییەک تەختەیەکی نوێ لە ناو play_one_game()دا وەردەگرێت.

Common mistakesهەڵە باوەکان

MistakeهەڵەWhat is trueڕاستییەکە
“Minimax looks only at good moves.”« تەنیا سەیری جووڵە باشەکان دەکات.»It looks at every move, good and bad, to the end of the game. That is why it is slow (alpha-beta fixes the speed).سەیری هەموو جووڵەیەک دەکات، باش و خراپ، تا کۆتایی یارییەکە. بۆیە خاوە ( خێراییەکە چاک دەکات).
Forgetting to undo a trial moveلەبیرچوونی گەڕاندنەوەی جووڵەیەکی تاقیکاریEvery board[row][col] = 'x' inside the search needs board[row][col] = ' ' after the recursive call.هەموو board[row][col] = 'x'ێک لە ناو گەڕانەکەدا دوای بانگکردنەوەی خۆبانگکەرەوە پێویستی بە board[row][col] = ' ' هەیە.
Swapping MAX and MINگۆڕینەوەی MAX و MINAfter x's trial move it is o's turn: call minimax(board, False); after o's, minimax(board, True).دوای جووڵەی تاقیکاریی x نۆرەی o ـە: minimax(board, False) بانگ بکە؛ دوای هی o، minimax(board, True).
Scoring every win +1هەژمارکردنی هەموو بردنەوەیەک بە ⁦+1⁩The AI may choose a slow win over a win now. Use depth-aware scores (10 − depth). ڕەنگە بردنەوەیەکی خاو لەسەر بردنەوەی ئێستا هەڵبژێرێت. بەپێی بەکار بهێنە (10 − depth).
Depth limit with no evaluation function بەبێ Every unfinished board looks like a draw; the AI is blind beyond the limit.هەموو تەختەیەکی تەواونەبوو وەک یەکسان دەردەکەوێت؛ لە دوای سنوورەکە کوێرە.

Exercisesڕاهێنانەکان

ExerciseڕاهێنانMinimax by handMinimax بە دەست

A MAX root has three MIN children. Their leaves are: A = (3, 5), B = (2, 9) and C = (6, 4). Which value does each MIN node get, which value does the root get, and which move does MAX choose?

MAX سێ منداڵی MIN ـی هەیە. ئەمانەن: ⁦A = (3⁩، ⁦5⁩)، ⁦B = (2⁩، ⁦9⁩) و ⁦C = (6⁩، ⁦4⁩). هەر MIN چ بەهایەک وەردەگرێت، چ بەهایەک وەردەگرێت و MAX کام جووڵە هەڵدەبژێرێت؟

Hintئاماژە

MIN nodes take the smaller leaf, then MAX takes the larger of those.

MIN گەڵا بچووکترەکە وەردەگرن، پاشان MAX گەورەترینیان وەردەگرێت.

Show answerوەڵامەکە پیشان بدە
  • A = min(3, 5) = 3, B = min(2, 9) = 2, C = min(6, 4) = 4.
  • Root = max(3, 2, 4) = 4, so MAX chooses C. B has the biggest leaf (9), but MIN would never allow it.
  • ⁦A = min(3⁩، ⁦5) = 3⁩، ⁦B = min(2⁩، ⁦9) = 2⁩، ⁦C = min(6⁩، ⁦4) = 4⁩.
  • = ⁦max(3⁩، 2، ⁦4) = 4⁩، بۆیە MAX C هەڵدەبژێرێت. B گەورەترین گەڵای هەیە ⁦(9)⁩، بەڵام MIN هەرگیز ڕێگەی پێ نادات.
ExerciseڕاهێنانLet the AI play oبا ژیریی دەستکرد بە o یاری بکات

In minimax_ai.py the AI is x and moves first. What must change so that the human (x) starts and the AI plays o?

لە minimax_ai.pyدا x ـە و یەکەم جار دەجووڵێت. چی دەبێت بگۆڕێت تاکو مرۆڤ ⁦(x)⁩ دەست پێبکات و بە o یاری بکات؟

Show answerوەڵامەکە پیشان بدە
  • In main(), the AI moves when player == 'o' and the human when player == 'x'.
  • The AI is now the MIN player: find_best_move places 'o', calls minimax(board, True) (x answers) and keeps the lowest score.
  • minimax and evaluate_board do not change: +1 is still good for x and −1 good for o.
  • لە main()دا، کاتێک دەجووڵێت کە player == 'o' بێت و مرۆڤ کاتێک player == 'x'.
  • ئێستا : find_best_move 'o' دادەنێت، minimax(board, True) بانگ دەکات (x وەڵام دەداتەوە) و نزمترین هەڵدەگرێت.
  • minimax و evaluate_board ناگۆڕێن: ⁦+1⁩ هێشتا بۆ x باشە و ⁦−1⁩ بۆ o.
ExerciseڕاهێنانWhy 549,945?بۆچی ⁦549,945⁩؟

The AI's first search visits 549,945 positions, but there are only 255,168 possible games. Explain the difference.

یەکەم گەڕانی سەردانی ⁦549,945⁩ شوێن دەکات، بەڵام تەنیا ⁦255,168⁩ یاریی ئەگەری هەیە. جیاوازییەکە ڕوون بکەرەوە.

Show answerوەڵامەکە پیشان بدە

A game is a path from the start to a finished board, so 255,168 is the number of leaves of the game tree. Minimax visits every node on every path: the finished boards and all the unfinished positions in between. The whole tree has 549,946 nodes; find_best_move handles the empty root itself, so count shows 549,945.

یارییەک لە سەرەتاوە بۆ تەختەیەکی کۆتاییهاتوو، بۆیە ⁦255,168⁩ ژمارەی . سەردانی هەموو دەکات لەسەر هەموو ڕێگەیەک: تەختە کۆتاییهاتووەکان و هەموو شوێنە تەواونەبووەکانی نێوانیان. هەموو دارەکە ⁦549,946⁩ هەیە؛ find_best_move خۆی مامەڵە لەگەڵ بەتاڵدا دەکات، بۆیە count ⁦549,945⁩ پیشان دەدات.

Summary and reviewکورتە و پێداچوونەوە

  • Minimax chooses a move in a two-player, zero-sum game by searching the game tree to the end.
  • Finished games score +1 (x wins), 0 (draw) or −1 (o wins). MAX (x) takes the highest child value, MIN (o) the lowest.
  • The code tries a move, calls itself (recursion), undoes the move, and keeps the max or min.
  • Score wins by depth (10 − depth) so the AI takes an immediate win; the course version ignored it in 291 positions.
  • A depth limit needs an evaluation function; easy/medium/hard levels come from random play and depth limits.
  • لە یارییەکی دوو یاریزانیدا، کە ، بە گەڕان لە تا کۆتایی، جووڵەیەک هەڵدەبژێرێت.
  • یاریی کۆتاییهاتوو ⁦+1 (x⁩ دەیباتەوە)، 0 (یەکسان) یان ⁦−1 (o⁩ دەیباتەوە) وەردەگرێت. ⁦MAX (x)⁩ بەرزترین بەهای منداڵەکان وەردەگرێت، ⁦MIN (o)⁩ نزمترین.
  • کۆدەکە جووڵەیەک تاقی دەکاتەوە، بانگی خۆی دەکاتەوە ()، جووڵەکە دەگەڕێنێتەوە و max یان min هەڵدەگرێت.
  • بردنەوە بەپێی هەژمار بکە ⁦(10 − depth)⁩ تاکو بردنەوەی دەستبەجێ وەربگرێت؛ وەشانی کۆرسەکە لە ⁦291⁩ شوێندا پشتگوێی خست.
  • پێویستی بە هەیە؛ ئاستەکانی ⁦easy/medium/hard⁩ لە یاریی هەڕەمەکی و دێن.
Review questionsپرسیارەکانی پێداچوونەوە
What do MAX and MIN mean in minimax?MAX و MIN لە Minimaxـدا چ واتایەکیان هەیە؟

MAX is the player who wants the highest score (our AI, x); MIN wants the lowest (the human, o).

MAX ئەو یاریزانەیە کە بەرزترین دەوێت ( ئێمە، x)؛ MIN نزمترینی دەوێت (مرۆڤ، o).

What is the main drawback of minimax?سەرەکیترین خراپیی Minimax چییە؟

It checks every future move, the bad ones too, so it is slow: 549,945 positions for the first move.

هەموو جووڵەیەکی داهاتوو دەپشکنێت، خراپەکانیش، بۆیە خاوە: ⁦549,945⁩ شوێن بۆ یەکەم جووڵە.

Why is count a list [0] and not a number?بۆچی count لیستێکە [0] و ژمارە نییە؟

A function may change the inside of a list without global; count[0] += 1 changes the item, not the name.

دەتوانێت ناوەوەی بگۆڕێت بەبێ global؛ count[0] += 1 دانەکە دەگۆڕێت، نەک ناوەکە.

Which move did the course's AI choose in the position of the game tree, and why?ژیریی دەستکردی کۆرسەکە لە شوێنی داری یارییەکەدا کام جووڵەی هەڵبژارد و بۆچی؟

0 0: it and 0 1 both score +1, and the code keeps the first of equal scores. With depth-aware scores it chooses 0 1 (score 9).

⁦0 0⁩: ئەم و ⁦0 1⁩ هەردووکیان ⁦+1⁩ وەردەگرن و کۆدەکە یەکەمی یەکسان هەڵدەگرێت. بە بەپێی ، ⁦0 1⁩ هەڵدەبژێرێت ( ⁦9⁩).

Videoڤیدیۆ

Watch a videoسەیری ڤیدیۆیەک بکە

A video that viewers liked a lot and praised in their comments, chosen for this lesson.ڤیدیۆیەک کە بینەران زۆریان پێ خۆش بووە و لە کۆمێنتەکانیاندا ستایشیان کردووە، بۆ ئەم وانەیە هەڵبژێردراوە.

Minimax: How Computers Play GamesSpanning Tree · Englishئینگلیزی · 274K viewsبینین · 9.7K likesلایک

Shows how minimax scores a tic-tac-toe game tree, MAX and MIN players, the pseudocode, and evaluation functions for games too big to search.

پیشان دەدات چۆن دەدات بە لە ، لەگەڵ و ، و بۆ ئەو یاریانەی زۆر گەورەن بۆ گەڕانی تەواو.

Whole video (14:36). 10:28–12:19 previews alpha-beta pruning, the next lesson; 12:19 onwards matches 'Difficulty levels'.

هەموو ڤیدیۆکە ⁦(14:36)⁩. لە ⁦10:28⁩ تا ⁦12:19⁩ پێشوەخت چاوێک بە دەخشێنێت، کە وانەی داهاتووە؛ لە ⁦12:19⁩ بەدواوە لەگەڵ شاشەی «ئاستەکانی قورسی» دەگونجێت.

Lesson complete!وانەکە تەواو بوو!

Well done. Review the key terms, then go on to the next lesson.دەستخۆش. سەیرێکی زاراوە سەرەکییەکان بکەرەوە، پاشان بڕۆ بۆ وانەی داهاتوو.

Key termsزاراوە سەرەکییەکان

Next lessonوانەی داهاتوو

Alpha-Beta Pruningبڕینی ئەلفا-بێتا

References and further readingسەرچاوەکان و خوێندنەوەی زیاتر

This lecture is a first edition. The Kurdish text and terminology are waiting for review by Kurdish IT teachers.ئەم وانەیە چاپی یەکەمە. دەقە کوردییەکە و زاراوەکانی چاوەڕێی پێداچوونەوەی مامۆستایانی کوردی بواری IT ن.