我最近了解了minimax,我正在努力制作一个无与伦比的AI井字游戏。我不知道为什么我的极小极大函数不起作用,我的电脑有时发挥非最佳行动。
这是我的完整代码:
from random import randint
import os
def play_again():
print()
t=True
while t:
p=input("Do you want to play again? Y or N ").upper()
if p=='Y' or p=='YES':
t=False
return True
elif p=='N' or p=='NO':
t=False
print("Thank You!!")
return False
else:
print('Enter a valid input!')
while True:
board1=['1','2','3','4','5','6','7','8','9']
print(' | |')
print(' ',board1[0],'|',board1[1],'|',board1[2])
print('____|___|____')
print(' | |')
print(' ',board1[3],'|',board1[4],'|',board1[5])
print('____|___|____')
print(' | |')
print(' ',board1[6],'|',board1[7],'|',board1[8])
print(' | |')
board=[' ',' ',' ',' ',' ',' ',' ',' ',' ']
def print_board():
print(' | |')
print(' ',board[0],'|',board[1],'|',board[2])
print('____|___|____')
print(' | |')
print(' ',board[3],'|',board[4],'|',board[5])
print('____|___|____')
print(' | |')
print(' ',board[6],'|',board[7],'|',board[8])
print(' | |')
if randint(0,1)==0:
player='Player 1'
else:
player='Player 2'
a='a'
while a not in ['X','O']:
a=input("Player 1: Do you want to be X or O: ").upper()
if a not in ['X','O']:
print("Enter valid output X or O")
if a=='X':
c='O'
else:
c='X'
def first():
if player=='Player 1':
print()
print('Player 1 will go first')
else:
print()
print('Player 2 will go first')
first()
def position_check():
return board[b-1] not in ['X','O']
def board_full():
for i in board:
if i not in ['X','O']:
return True
return False
def win_check(m):
return ((board[0]==m and board[1]==m and board[2]==m) or
(board[3]==m and board[4]==m and board[5]==m) or
(board[6]==m and board[7]==m and board[8]==m) or
(board[0]==m and board[3]==m and board[6]==m) or
(board[1]==m and board[4]==m and board[7]==m) or
(board[2]==m and board[5]==m and board[8]==m) or
(board[0]==m and board[4]==m and board[8]==m) or
(board[2]==m and board[4]==m and board[6]==m))
def minimax(board,depth,ismax):
if win_check(c):
return 1
elif win_check(a):
return -1
elif not board_full:
return 0
if ismax:
bestscore = -1000
for i in range(len(board)):
if board[i]==' ':
board[i]=c
score= minimax(board,depth+1,False)
board[i]=' '
if score > bestscore:
bestscore = score
return bestscore
else:
bestscore = 1000
for i in range(len(board)):
if board[i]==' ':
board[i]=a
score= minimax(board,depth+1,True)
board[i]=' '
if score < bestscore:
bestscore = score
return bestscore
while board_full():
if player=='Player 1':
b='a'
within_range=False
while b.isdigit()==False or within_range==False:
b=input("Enter your next move (1-9) :")
if b.isdigit()==False:
print('\n'*100)
print('Enter a choice between 1-9')
if b.isdigit()==True:
if int(b) in range(1,10):
within_range=True
else:
print('Enter a choice between 1-9')
b=int(b)
if position_check():
board[b-1]=a
print_board()
if win_check(a):
print('Congratulations Player 1 wins!!')
break
else:
player='Player 2'
else:
print('Position already occupied')
if player=='Player 2':
bestscore = -1000
for i in range(len(board)):
if board[i]==' ':
board[i]=c
score= minimax(board,0,False)
board[i]=' '
if score > bestscore:
bestscore = score
bestmove=i
b=bestmove
if position_check:
board[b]=c
print_board()
if win_check(c):
print('Congratulations Player 2 wins!!')
break
else:
player='Player 1'
else:
print('Its a DRAW!!')
if not play_again():
break
字符串
当我玩位置1时,comp应该玩位置5,但它没有,但它总是玩位置2,最终失去了我的代码中的错误在哪里我刚刚学习了minimax,我不想使用深度概念:
| |
1 | 2 | 3
____|___|____
| |
4 | 5 | 6
____|___|____
| |
7 | 8 | 9
| |
Player 1: Do you want to be X or O: x
Player 1 will go first
Enter your next move (1-9) :1
| |
X | |
____|___|____
| |
| |
____|___|____
| |
| |
| |
| |
X | O |
____|___|____
| |
| |
____|___|____
| |
| |
| |
型
1条答案
按热度按时间rur96b6h1#
存在以下几个问题:
minimax
这个语句中:字符串
这个条件永远不会满足,因为您评估的是函式对象,而不是 * 呼叫 * 函式的结果。
这应该是:
型
我应该说这个函数的名称是误导性的。当棋盘未满时,
board_full
返回True(真),尽管它的名称是空的。你最好换个说法,比如:board_has_moves
的值。型
这个条件总是成立的,即使当游戏结束,所以计算机得到发挥他们的最后一个迭代的举动(即。9)--用无效移动覆盖该单元。
它应该有括号。
position_check
显然期望b
的值是从1开始的,因为它与b-1
一起工作,但是计算机移动被存储在b
中作为从0开始的值。因此position_check
将无法与之正常工作。我建议您始终使用从0开始的b
值,并调整position_check
以使用b
,而不是b-1
。人类玩家的走法可以通过b=int(b) - 1
来正确设置if
区块 ,而不会首先检查游戏是否结束!.如果已经实现了上述所有修复程序,这仍然可以正常工作,但最好将if player=='Player 2':
语句设置为else:
语句。这样,主循环将只执行两个块中的一个,而不会在同一个迭代中同时执行两个块。不成问题,但是:
a
、b
和c
这样的名称是没有意义的,并且会使代码更难阅读。如果您将它们命名为player_1_symbol
、move
、player_2_symbol
,则会更清楚play_again
中,不需要名称t
。就做一个while True:
。position_check
和其他函数,应该将一些值作为函数参数传递--无论如何,这都是一种很好的做法。minimax
定义为局部函数,因此,对于这个递归函数,参数的数量可以保持很小。main()
。这会使全局名称变为本地名称,并强制您传递参数--这是一个很好的实践。当然还有很多需要改进的地方,但是上面的更改(以及其他一些更改)导致了您的代码的以下版本:
型