python - tic tac toe minimax 函数上的无效动作错误
问题描述
我正在尝试在cs50ai中为tic tac toe编写一个minimax算法,但我似乎无法理解它。我似乎无法理解如何从 maxval 和 minval 之间的递归中获取值。我的脚本如何找到游戏状态的值并将其与无限值进行比较,以及如何将该值与 for 循环检查的初始移动相关联?目前我的代码总是引发无效操作的异常。这让我觉得它一直在运行,直到板为空,然后尝试执行另一个操作。我已经做了很多阅读和查看不同的代码,但我不知道如何使这项工作。任何帮助和提示表示赞赏。
"""
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.
"""
if terminal(board):
return None
if board == initial_state():
return X
if checkturn(board) == X:
return X
elif checkturn(board) == O:
return O
#return turn
#raise NotImplementedError
def actions(board):
"""
Returns set of all possible actions (i, j) available on the board.
"""
action_set = set()
coord_x = 0
coord_y = 0
board_size = 3
for row in board:
for item in row:
if item is None:
action_set.add((coord_x, coord_y))
coord_y += 1
if coord_y == board_size:
coord_y = 0
coord_x += 1
return action_set
#raise NotImplementedError
def result(board, action):
"""
Returns the board that results from making move (i, j) on the board.
"""
# If the action is not in the action set raise an exception that the move is invalid
#
# DISCUSS THIS WITH HAMISH
action_set = actions(board)
# Make a copy of the previous boards to reference
parentboard = copy.deepcopy(board)
if parentboard[action[0]][action[1]] is not None:
raise Exception("Invalid action")
#Make a new updated board to return so we don't overwrite the old ones
if action in action_set:
newboard = board
newboard[action[0]][action[1]] = player(board)
return newboard
def winner(board):
"""
Returns the winner of the game, if there is one.
"""
row = [[board[0][0], board[0][1], board[0][2]],
[board[1][0], board[1][1], board[1][2]],
[board[2][0], board[2][1], board[2][2]]]
col = [[board[0][0], board[1][0], board[2][0]],
[board[0][1], board[1][1], board[2][1]],
[board[0][2], board[1][2], board[2][2]]]
diag = [[board[0][0], board[1][1], board[2][2]],
[board[2][0], board[1][1], board[0][2]]]
for item in row:
win = check_xo(item)
if win is not None:
return win
for item in col:
check_xo(item)
if win is not None:
return win
for item in diag:
check_xo(item)
if win is not None:
return win
#raise NotImplementedError
def terminal(board):
"""
Returns True if game is over, False otherwise.
"""
action_set = actions(board)
# Check if the actionset is empty. IF so game is over(True)
if len(action_set) == 0:
return True
# Check if someone has won the game. If so game is over (True).
if winner(board) == X or winner(board) == O:
return True
else:
return False
#raise NotImplementedError
def utility(board):
"""
Returns 1 if X has won the game, -1 if O has won, 0 otherwise.
"""
if winner(board) == X:
return 1
elif winner(board) == O:
return -1
elif winner(board) is None:
return 0
#raise NotImplementedError
def minimax(board):
"""
Returns the optimal action for the current player on the board.
"""
#if terminal(board):
# return None
if player(board) == X:
v = -math.inf
for action in actions(board):
v = minval(result(board, action))
if v > value:
return action
if player(board) == O:
v = math.inf
for action in actions(board):
v = maxval(result(board, action))
if v < value:
return action
# My added functions start #
def maxval(board):
if terminal(board):
return utility(board)
value = -math.inf
for action in actions(board):
max(value, minval(result(board, action)))
return value
# Find the move that produces the highest Value
def minval(board):
if terminal(board):
return utility(board)
value = -math.inf
for action in actions(board):
min(value, maxval(result(board, action)))
return value
def checkturn(board):
xCount = 0
oCount = 0
# Count how many Os and Xs are on the board
for i in board:
for j in i:
if j == X:
xCount += 1
if j == O:
oCount += 1
#If O is less than x, then it's O's turn, otherwise it's Xs turn
if oCount < xCount:
return O
else:
return X
def check_xo(item):
if item == ['X', 'X', 'X']:
return X
if item == ['O', 'O', 'O']:
return O
else:
return None
解决方案
我正在尝试做同样的事情,但是每当我运行我的代码时,我都会选择我的播放器并放一个动作然后下一回合出错
推荐阅读
- python - 如何在 Python 中清除屏幕?
- google-chrome - 是否可以在 Google Chrome 开发者工具中更改标尺线的颜色?
- mongodb - 按时间、日期和月份对 mongodb 聚合进行排序
- android - 是否有可能使用 Reader SDK 以编程方式更改 Square 键?
- javascript - 根据数据属性设置cookie
- triggers - Zabbix 3.4.15 发现触发器:如何在触发器名称中添加发现参数{#SERIAL}?
- excel - 根据某些特定字符提取字符串
- ios - 如何在 Apple Connect 中获取 ProductID?(应用内购买)
- c# - 我在我的服务总线队列中调用了一个长时间运行的进程。我希望它持续超过 5 分钟
- c++ - 分离线程中的竞争条件