问题描述
我正在努力查看我的极小极大算法是如何工作的。它在所有最好的动作中循环,但它没有选择最好的动作,我不知道为什么。例如,我可以输入 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,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,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,True)
board[key] = ' '
if (score < bestscore):
bestscore = score
return bestscore
start()
抱歉乱码,先谢谢了
解决方法
看起来你把事情复杂化了,你用更少的代码来调试会更容易。我首先建议您使用列表而不是字典来简化此游戏中的代码:board = [' ']*9
。我在下面的所有建议/简化都基于这种表示。
1.. 在 1D 棋盘上检查获胜非常容易。首先,您创建一个包含所有可能获胜线的变量:
winning_lines = ([0,1,2],[3,4,5],[6,7,8],[0,3,6],[1,7],[2,5,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 返回语句中添加和减去深度。
4..您可以通过列表推导获得所有可能的移动:
possible_moves = [i for i in range(len(board)) if board[i] == ' ']
调试
还有一些其他的清理工作要做,但要弄清楚为什么它给出了错误的答案,您需要进行一些调试。您的赢/平/输功能是否像您认为的那样工作,即它是否为已知输入板返回正确结果?它是否遍历所有可能的移动?在您的极小极大循环中打印内容,看看它的行为是否符合您的预期。