努力了解为什么我的井字游戏 minimax 游戏没有选择最佳着法 - python
Struggling to see why my tic tac toe minimax game is not picking the best move - python
我正在努力查看我的 minimax 算法是如何不起作用的。它循环遍历所有最佳动作,但没有选择最佳动作,我不明白为什么。例如,我可以输入 1 5 9 并获胜。如果解决方案很简单,请提前抱歉
这是代码。
board = {1: ' ', 2: ' ', 3: ' ',
4: ' ', 5: ' ', 6: ' ',
7: ' ', 8: ' ', 9: ' '}
win = False
turn = 1
depth = 1
nodeindex = 0
possibles= []
moves = []
depth = 0
targetdepth = 3
movesdone = []
#def minimax(moves, targetdepth, depth, turn, scores):
def checkForWin(mark):
if board[1] == board[2] and board[1] == board[3] and board[1] == mark:
return True
elif (board[4] == board[5] and board[4] == board[6] and board[4] == mark):
return True
elif (board[7] == board[8] and board[7] == board[9] and board[7] == mark):
return True
elif (board[1] == board[4] and board[1] == board[7] and board[1] == mark):
return True
elif (board[2] == board[5] and board[2] == board[8] and board[2] == mark):
return True
elif (board[3] == board[6] and board[3] == board[9] and board[3] == mark):
return True
elif (board[1] == board[5] and board[1] == board[9] and board[1] == mark):
return True
elif (board[7] == board[5] and board[7] == board[3] and board[7] == mark):
return True
else:
return False
def checkForWin2():
if (board[1] == board[2] and board[1] == board[3] and board[1] != ' '):
return True
elif (board[4] == board[5] and board[4] == board[6] and board[4] != ' '):
return True
elif (board[7] == board[8] and board[7] == board[9] and board[7] != ' '):
return True
elif (board[1] == board[4] and board[1] == board[7] and board[1] != ' '):
return True
elif (board[2] == board[5] and board[2] == board[8] and board[2] != ' '):
return True
elif (board[3] == board[6] and board[3] == board[9] and board[3] != ' '):
return True
elif (board[1] == board[5] and board[1] == board[9] and board[1] != ' '):
return True
elif (board[7] == board[5] and board[7] == board[3] and board[7] != ' '):
return True
else:
return False
def possiblemoves(board):
y=0
possibles.clear()
for i in board:
if board[i] == " ":
possibles.append(i)
return possibles
def botgo(possibles, mark):
bestscore = -800
bestmove = 0
for key in board.keys():
if (board[key] == ' '):
board[key] = mark
score = minimax(board,0,False)
board[key] = ' '
if(score > bestscore):
bestscore = score
bestmove = key
insert(bestmove,mark='O')
return
def printboard():
print(board[1] + '|' + board[2] + '|' + board[3])
print('-----')
print(board[4] + '|' + board[5] + '|' + board[6])
print('-----')
print(board[7] + '|' + board[8] + '|' + board[9])
def start():
turn = 1
count = 0
while count != 9:
humango()
printboard()
possiblemoves(board)
botgo(possibles, mark='O')
printboard()
count = count + 1
#minimax(depth, possibles)
def spacefree(space):
if board[space] == ' ':
return True
else:
return False
def insert(space, mark):
if spacefree(space):
board[space]=mark
if checkForWin(mark):
if mark == 'X':
printboard()
print("human win")
exit()
else:
printboard()
print("BOT WIN")
exit()
else:
print("cannot insert there!!!")
space = int(input("Enter position"))
insert(space, mark)
def checkdraw(board):
if checkForWin2():
return True
def humango():
global turn
space = int(input("Enter position"))
insert(space, mark='X')
turn = turn + 1
printboard()
def minimax(board, depth, ismax):
if checkForWin(mark='O'):
return 1
elif checkForWin(mark='X'):
return -1
elif checkdraw(board):
return 0
if ismax == True:
bestscore = -800
for key in board.keys():
if (board[key] == ' '):
board[key] = 'O'
score = minimax(board, depth + 1, False)
board[key] = ' '
if (score > bestscore):
bestscore = score
printboard()
return bestscore
else:
bestscore = 800
for key in board.keys():
if (board[key] == ' '):
board[key] = 'X'
score = minimax(board, depth + 1, True)
board[key] = ' '
if (score < bestscore):
bestscore = score
return bestscore
start()
抱歉代码乱七八糟,先谢谢了
看来你把事情复杂化了,你调试起来会更容易,代码更少,看得更清楚。我首先建议您使用列表而不是字典来简化您在这个游戏中的代码:board = [' ']*9
。我下面的所有suggestions/simplifications都是基于这个表示。
1.. 在 1D 棋盘上检查是否获胜非常容易。首先,您创建一个包含所有可能获胜线的变量:
winning_lines = ([0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6])
然后你可以用一个循环遍历它们:
def is_win(board, player):
for pos in winning_lines:
if board[pos[0]] == board[pos[1]] == board[pos[2]] == player:
return 1
2.. 检查平局更简单,因为你只需要检查是否有空格:
def is_draw(board):
return 0 if ' ' in board else 1
3.. 在此游戏中您不需要深度变量,因为您总是达到最大深度,以赢、平或输告终。如果有超过 1 条路径,深度可用于始终选择最短的获胜路径,或最长的失败路径。然后你需要在 minimax 循环中从你的 check_win return 语句中添加和减去深度。
4.. 你可以通过列表理解得到所有可能的走法:
possible_moves = [i for i in range(len(board)) if board[i] == ' ']
调试
还有一些其他的清理工作要做,但要弄清楚为什么它会给出错误的答案,您需要进行一些调试。您的 win/draw/loss 功能是否如您所想的那样工作,即它是否 return 是已知输入板的正确结果?它会遍历所有可能的动作吗?在你的 minimax 循环中打印一些东西,看看它的行为是否如你所期望的那样。
我正在努力查看我的 minimax 算法是如何不起作用的。它循环遍历所有最佳动作,但没有选择最佳动作,我不明白为什么。例如,我可以输入 1 5 9 并获胜。如果解决方案很简单,请提前抱歉 这是代码。
board = {1: ' ', 2: ' ', 3: ' ',
4: ' ', 5: ' ', 6: ' ',
7: ' ', 8: ' ', 9: ' '}
win = False
turn = 1
depth = 1
nodeindex = 0
possibles= []
moves = []
depth = 0
targetdepth = 3
movesdone = []
#def minimax(moves, targetdepth, depth, turn, scores):
def checkForWin(mark):
if board[1] == board[2] and board[1] == board[3] and board[1] == mark:
return True
elif (board[4] == board[5] and board[4] == board[6] and board[4] == mark):
return True
elif (board[7] == board[8] and board[7] == board[9] and board[7] == mark):
return True
elif (board[1] == board[4] and board[1] == board[7] and board[1] == mark):
return True
elif (board[2] == board[5] and board[2] == board[8] and board[2] == mark):
return True
elif (board[3] == board[6] and board[3] == board[9] and board[3] == mark):
return True
elif (board[1] == board[5] and board[1] == board[9] and board[1] == mark):
return True
elif (board[7] == board[5] and board[7] == board[3] and board[7] == mark):
return True
else:
return False
def checkForWin2():
if (board[1] == board[2] and board[1] == board[3] and board[1] != ' '):
return True
elif (board[4] == board[5] and board[4] == board[6] and board[4] != ' '):
return True
elif (board[7] == board[8] and board[7] == board[9] and board[7] != ' '):
return True
elif (board[1] == board[4] and board[1] == board[7] and board[1] != ' '):
return True
elif (board[2] == board[5] and board[2] == board[8] and board[2] != ' '):
return True
elif (board[3] == board[6] and board[3] == board[9] and board[3] != ' '):
return True
elif (board[1] == board[5] and board[1] == board[9] and board[1] != ' '):
return True
elif (board[7] == board[5] and board[7] == board[3] and board[7] != ' '):
return True
else:
return False
def possiblemoves(board):
y=0
possibles.clear()
for i in board:
if board[i] == " ":
possibles.append(i)
return possibles
def botgo(possibles, mark):
bestscore = -800
bestmove = 0
for key in board.keys():
if (board[key] == ' '):
board[key] = mark
score = minimax(board,0,False)
board[key] = ' '
if(score > bestscore):
bestscore = score
bestmove = key
insert(bestmove,mark='O')
return
def printboard():
print(board[1] + '|' + board[2] + '|' + board[3])
print('-----')
print(board[4] + '|' + board[5] + '|' + board[6])
print('-----')
print(board[7] + '|' + board[8] + '|' + board[9])
def start():
turn = 1
count = 0
while count != 9:
humango()
printboard()
possiblemoves(board)
botgo(possibles, mark='O')
printboard()
count = count + 1
#minimax(depth, possibles)
def spacefree(space):
if board[space] == ' ':
return True
else:
return False
def insert(space, mark):
if spacefree(space):
board[space]=mark
if checkForWin(mark):
if mark == 'X':
printboard()
print("human win")
exit()
else:
printboard()
print("BOT WIN")
exit()
else:
print("cannot insert there!!!")
space = int(input("Enter position"))
insert(space, mark)
def checkdraw(board):
if checkForWin2():
return True
def humango():
global turn
space = int(input("Enter position"))
insert(space, mark='X')
turn = turn + 1
printboard()
def minimax(board, depth, ismax):
if checkForWin(mark='O'):
return 1
elif checkForWin(mark='X'):
return -1
elif checkdraw(board):
return 0
if ismax == True:
bestscore = -800
for key in board.keys():
if (board[key] == ' '):
board[key] = 'O'
score = minimax(board, depth + 1, False)
board[key] = ' '
if (score > bestscore):
bestscore = score
printboard()
return bestscore
else:
bestscore = 800
for key in board.keys():
if (board[key] == ' '):
board[key] = 'X'
score = minimax(board, depth + 1, True)
board[key] = ' '
if (score < bestscore):
bestscore = score
return bestscore
start()
抱歉代码乱七八糟,先谢谢了
看来你把事情复杂化了,你调试起来会更容易,代码更少,看得更清楚。我首先建议您使用列表而不是字典来简化您在这个游戏中的代码:board = [' ']*9
。我下面的所有suggestions/simplifications都是基于这个表示。
1.. 在 1D 棋盘上检查是否获胜非常容易。首先,您创建一个包含所有可能获胜线的变量:
winning_lines = ([0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6])
然后你可以用一个循环遍历它们:
def is_win(board, player):
for pos in winning_lines:
if board[pos[0]] == board[pos[1]] == board[pos[2]] == player:
return 1
2.. 检查平局更简单,因为你只需要检查是否有空格:
def is_draw(board):
return 0 if ' ' in board else 1
3.. 在此游戏中您不需要深度变量,因为您总是达到最大深度,以赢、平或输告终。如果有超过 1 条路径,深度可用于始终选择最短的获胜路径,或最长的失败路径。然后你需要在 minimax 循环中从你的 check_win return 语句中添加和减去深度。
4.. 你可以通过列表理解得到所有可能的走法:
possible_moves = [i for i in range(len(board)) if board[i] == ' ']
调试
还有一些其他的清理工作要做,但要弄清楚为什么它会给出错误的答案,您需要进行一些调试。您的 win/draw/loss 功能是否如您所想的那样工作,即它是否 return 是已知输入板的正确结果?它会遍历所有可能的动作吗?在你的 minimax 循环中打印一些东西,看看它的行为是否如你所期望的那样。