#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)
казалось, решила проблему. Я действительно не вижу разницы ни в циклах, ни в их функциональности.