Агент ИИ работает только в первой строке

#python #artificial-intelligence #cs50 #game-theory

#питон #искусственный интеллект #cs50 #теория игр

Вопрос:

Я делаю проект cs50 AI tic-tac-toe. Я завершил всю кодовую базу, но мне кажется, что агент выполняет перемещения только в первой строке сетки. Кроме того, если первый ряд сетки заполнен, игра отображается как «ничья». Это мой код:

 """
Tic Tac Toe Player
"""

import math
import copy

X = "X"
O = "O"
EMPTY = None


def initial_state():
   """
   Returns starting state of the board.
   """
   return [[EMPTY, EMPTY, EMPTY],
           [EMPTY, EMPTY, EMPTY],
           [EMPTY, EMPTY, EMPTY]]


def player(board):
   """
   Returns player who has the next turn on a board.
   """
   #Initialize number of X's and O's in the board
   sum_X = 0
   sum_O = 0
   #Count the number of variables each time
   for i in board:
       sum_X =i.count(X)
       sum_O =i.count(O)
   # If X>O, then the player has to be O, but if X<O(which won't really happen ever) or X=O, naturally the player has to be X
   if sum_X>sum_O:
       return O
   else:
       return X


def actions(board):
   """
   Returns set of all possible actions (i, j) available on the board.
   """
   #Initialize a dictionary to track all the empty spots on the board
   i=0
   j=0
   possible_actions=set()
   while i<3:
       while j<3:
           if board[i][j] == EMPTY:
               possible_actions.add((i,j))
           j =1 
       i =1
   return possible_actions


def result(board, action):
   """
   Returns the board that results from making move (i, j) on the board.
   """
   #Generate deep copy
   board_deepcopy = copy.deepcopy(board)
   try:
       if board_deepcopy[action[0]][action[1]]:
           raise IndexError
       else:
           board_deepcopy[action[0]][action[1]] = player(board_deepcopy)
           return board_deepcopy
   except IndexError:
       print('Spot occupied already')


def winner(board):
   """
   Returns the winner of the game, if there is one.
   """
   #Horizontal check

   for i in board:
       if i.count(X)==3:
           return X
       elif i.count(O)==3:
           return O

   #Vertical check
   j=0
   while j<3:
       i=0
       vert_check=[]
       while i<3:
           vert_check.append(board[i][j])
           i =1
       if vert_check.count(X)==3:
           return X
       elif vert_check.count(O)==3:
           return O
       j =1

   #Diagonal check
   i=0
   diag_check_1=[]
   diag_check_2=[]
   while i<3:
       diag_check_1.append(board[i][i])#top left to bottom right
       diag_check_2.append(board[i][2-i])#top right to bottom left
       i =1
   if diag_check_1.count(X)==3 or diag_check_2.count(X)==3:
       return X
   elif diag_check_1.count(O)==3 or diag_check_2.count(O)==3:
       return O

   return None


def terminal(board):
   """
   Returns True if game is over, False otherwise.
   """
   #Game either ends if a winner is declared or if there is a tie i.e. there are no more actions left
   if winner(board):
       return True
   elif not actions(board):
       return True
   else:
       return False


def utility(board):
   """
   Returns 1 if X has won the game, -1 if O has won, 0 otherwise.
   """
   if terminal(board):
       if winner(board) == X:
           return 1
       elif winner(board) == O:
           return -1
       else:
           return 0


def minimax(board):
   """
   Returns the optimal action for the current player on the board.
   """
   current_player = player(board)

   if current_player == X:
       v = -math.inf
       for action in actions(board):
           k = minimize(result(board, action))
           if k > v:
               v = k
               best_move = action
   else:
       v = math.inf
       for action in actions(board):
           k = maximize(result(board, action))
           if k < v:
               v = k
               best_move = action
   return best_move


def maximize(board):
   if terminal(board):
       return utility(board)
   v = -math.inf
   for action in actions(board):
       v=max(v,minimize(result(board, action)))
       return v


def minimize(board):
   if terminal(board):
       return utility(board)
   v = math.inf
   for action in actions(board):
       v=min(v,maximize(result(board, action)))
       return v
 

Ходы также не являются оптимальными, так как он перемещается только в первом ряду. Набор possible_moves содержит все возможные перемещения во всех строках, так что на самом деле это не проблема.

Комментарии:

1. На этот вопрос было бы намного проще ответить, если бы вы могли точно определить, в какой функции проблема.

2. Я попытался заменить функции, и проблема, похоже, была в actions() функции. Замена на while i<3: while j<3 , i in range(3): j in range(3) казалось, решила проблему. Я действительно не вижу разницы ни в циклах, ни в их функциональности.