如何修复井字游戏的极小极大算法
How to fix my minimax algorithm for tic tac toe game
对于一个学校项目,我一直在尝试制作一款无与伦比的井字游戏。为此,我尝试实现一个 minimax 算法,它给出了意想不到的输出,我一直无法弄清楚原因,也没有解决任何问题。
我已经尝试打印出变量以查看何时出现问题,但是对于比最简单的情况(它在其中工作)更复杂的任何事情,它输出的东西太多以至于任何人都无法筛选,并且当我完成它,跟踪调用自身的函数,以及它调用自身的次数是很困难的。我试过将严格的不等式改为非严格的不等式。我试过几次重写整个事情,看看我是否只是有错字。我已经逐步了解了逻辑,但一无所获。
这是我的算法
def minimax(newboard, player, huplayer, aiplayer):
move=-1
empty=emptyindices(newboard)
if winning(newboard, huplayer):
score=-1
elif winning(newboard, aiplayer):
score = 1
elif empty==[]:
score=0
else:
if player == aiplayer:
score=0
for i in empty:
newboard[i]=player
output=minimax(newboard, huplayer, huplayer, aiplayer)
tempscore=output[1]
if tempscore > score:
score=tempscore
move = i
newboard[i]=""
newboard[i]=""
if player == huplayer:
score=0
for i in empty:
newboard[i]=player
output=minimax(newboard, aiplayer, huplayer, aiplayer)
tempscore=output[1]
if tempscore < score:
score=tempscore
move = i
newboard[i]=""
newboard[i]=""
return [move,score]
我已经将电路板从 0 索引到 8,就像
0 | 1 | 2
3 | 4 | 5
6 | 7 | 8
我不认为使用的其他函数有错误,但我还是会把它们包括在这里,以防它们确实是问题所在。
def winning(board,player):
if (board[0]==player and board[1]==player and board[2]==player) or (board[3]==player and board[4]==player and board[5]==player) or(board[6]==player and board[7]==player and board[8]==player) or(board[0]==player and board[3]==player and board[6]==player) or (board[1]==player and board[4]==player and board[7]==player) or(board[2]==player and board[5]==player and board[8]==player) or (board[0]==player and board[4]==player and board[8]==player) or (board[2]==player and board[4]==player and board[6]==player):
win=True
else:
win=False
return win
def emptyindices(board):
empty=[]
for i in range(9):
if board[i]=="":
empty.append(i)
return empty
对于计算机可以立即采取行动获胜的简单情况,它会这样做。
但是对于
这样的东西
print(minimax(['X', '', '', 'O', '', 'X', 'X', 'O', 'O'],"X","O","X"))
输出是
[-1, 0]
即使计算机可以通过移动 2 来保证获胜,这意味着由于某种原因移动没有从默认值改变
我认为这应该可行(我刚刚测试了我在评论中提出的建议)。可怜的输家球员太瘫痪了,无法采取行动,认识到这是不可避免的命运:-)
def minimax(newboard, player, huplayer, aiplayer):
move=-1
empty=emptyindices(newboard)
if winning(newboard, huplayer):
score=-1
elif winning(newboard, aiplayer):
score = 1
elif empty==[]:
score=0
else:
if player == aiplayer:
score=-2
for i in empty:
newboard[i]=player
output=minimax(newboard, huplayer, huplayer, aiplayer)
tempscore=output[1]
if tempscore > score:
score=tempscore
move = i
newboard[i]=""
newboard[i]=""
if player == huplayer:
score=2
for i in empty:
newboard[i]=player
output=minimax(newboard, aiplayer, huplayer, aiplayer)
tempscore=output[1]
if tempscore < score:
score=tempscore
move = i
newboard[i]=""
newboard[i]=""
return [move,score]
不错的功能!
顺便说一句。您可以通过为分数使用一个因子来使代码更短一些。因此,对于最小化玩家,您将因子设置为 -1,将最大化设置为 1。这样您就可以重复使用空字段上的循环和两个玩家的循环体,而无需通过将条件更改为类似的东西来实现两次:
if tempscore*factor > score:
对于一个学校项目,我一直在尝试制作一款无与伦比的井字游戏。为此,我尝试实现一个 minimax 算法,它给出了意想不到的输出,我一直无法弄清楚原因,也没有解决任何问题。
我已经尝试打印出变量以查看何时出现问题,但是对于比最简单的情况(它在其中工作)更复杂的任何事情,它输出的东西太多以至于任何人都无法筛选,并且当我完成它,跟踪调用自身的函数,以及它调用自身的次数是很困难的。我试过将严格的不等式改为非严格的不等式。我试过几次重写整个事情,看看我是否只是有错字。我已经逐步了解了逻辑,但一无所获。
这是我的算法
def minimax(newboard, player, huplayer, aiplayer):
move=-1
empty=emptyindices(newboard)
if winning(newboard, huplayer):
score=-1
elif winning(newboard, aiplayer):
score = 1
elif empty==[]:
score=0
else:
if player == aiplayer:
score=0
for i in empty:
newboard[i]=player
output=minimax(newboard, huplayer, huplayer, aiplayer)
tempscore=output[1]
if tempscore > score:
score=tempscore
move = i
newboard[i]=""
newboard[i]=""
if player == huplayer:
score=0
for i in empty:
newboard[i]=player
output=minimax(newboard, aiplayer, huplayer, aiplayer)
tempscore=output[1]
if tempscore < score:
score=tempscore
move = i
newboard[i]=""
newboard[i]=""
return [move,score]
我已经将电路板从 0 索引到 8,就像
0 | 1 | 2
3 | 4 | 5
6 | 7 | 8
我不认为使用的其他函数有错误,但我还是会把它们包括在这里,以防它们确实是问题所在。
def winning(board,player):
if (board[0]==player and board[1]==player and board[2]==player) or (board[3]==player and board[4]==player and board[5]==player) or(board[6]==player and board[7]==player and board[8]==player) or(board[0]==player and board[3]==player and board[6]==player) or (board[1]==player and board[4]==player and board[7]==player) or(board[2]==player and board[5]==player and board[8]==player) or (board[0]==player and board[4]==player and board[8]==player) or (board[2]==player and board[4]==player and board[6]==player):
win=True
else:
win=False
return win
def emptyindices(board):
empty=[]
for i in range(9):
if board[i]=="":
empty.append(i)
return empty
对于计算机可以立即采取行动获胜的简单情况,它会这样做。 但是对于
这样的东西print(minimax(['X', '', '', 'O', '', 'X', 'X', 'O', 'O'],"X","O","X"))
输出是
[-1, 0]
即使计算机可以通过移动 2 来保证获胜,这意味着由于某种原因移动没有从默认值改变
我认为这应该可行(我刚刚测试了我在评论中提出的建议)。可怜的输家球员太瘫痪了,无法采取行动,认识到这是不可避免的命运:-)
def minimax(newboard, player, huplayer, aiplayer):
move=-1
empty=emptyindices(newboard)
if winning(newboard, huplayer):
score=-1
elif winning(newboard, aiplayer):
score = 1
elif empty==[]:
score=0
else:
if player == aiplayer:
score=-2
for i in empty:
newboard[i]=player
output=minimax(newboard, huplayer, huplayer, aiplayer)
tempscore=output[1]
if tempscore > score:
score=tempscore
move = i
newboard[i]=""
newboard[i]=""
if player == huplayer:
score=2
for i in empty:
newboard[i]=player
output=minimax(newboard, aiplayer, huplayer, aiplayer)
tempscore=output[1]
if tempscore < score:
score=tempscore
move = i
newboard[i]=""
newboard[i]=""
return [move,score]
不错的功能!
顺便说一句。您可以通过为分数使用一个因子来使代码更短一些。因此,对于最小化玩家,您将因子设置为 -1,将最大化设置为 1。这样您就可以重复使用空字段上的循环和两个玩家的循环体,而无需通过将条件更改为类似的东西来实现两次:
if tempscore*factor > score: