【发布时间】:2019-09-22 21:02:33
【问题描述】:
我对编程并不陌生,但我之前没有按照教程尝试过制作太多东西。这是我第一次尝试真正的项目,而不遵循视频或复制粘贴代码。我创建了一个简单的井字游戏,如果两个玩家都手动选择位置,它可以正常工作,但是当我尝试使用 minimax 算法实现一个简单的 AI 时,它会一次播放所有 AI 动作,我不知道为什么。
我多次查看代码,但我不明白为什么当玩家只能移动 1 步时 AI 可以继续放置棋子/移动。根据代码,一次只允许 1 次移动。到底是怎么回事?当轮到人工智能时,人工智能会放置棋子直到它获胜,而不考虑轮到什么的。玩家棋子也被放置,这很奇怪,因为需要提示玩家进行选择输入。我认为问题出在 minimax 函数本身,但我无法确定在哪里。任何帮助将不胜感激!非常感谢。完整文件:
import random
from time import sleep
from math import inf
PLAYER = 0
AI = 1
BOARD = [[' ', ' ', ' '],
[' ', ' ', ' '],
[' ', ' ', ' ']]
#AVAILABLE = [[0,0],[0,1],[0,2],[1,0],[1,1],[1,2],[2,0],[2,1],[2,2]]
AVAILABLE = [1,2,3,4,5,6,7,8,9]
SELECTION = 0
TURN = random.randint(0, 1)
def display_board(board):
print(f'\t[{board[0][0]}] [{board[0][1]}] [{board[0][2]}]\n\t[{board[1][0]}] [{board[1][1]}] [{board[1][2]}]\n\t[{board[2][0]}] [{board[2][1]}] [{board[2][2]}]')
def convert_position(available_locations, position):
if position in available_locations:
available_locations.remove(position)
position -= 1
converted = (position // 3, position % 3)
return converted
def is_valid_location(board):
pass
def place_piece(board, position, player):
a, b = position
if a in [0, 1, 2] and b in [0, 1, 2]:
if board[a][b] == ' ' and player == PLAYER:
board[a][b] = 'X'
if board[a][b] == ' ' and player == AI:
board[a][b] = 'O'
def clear_board(board):
board = [[' ', ' ', ' '],
[' ', ' ', ' '],
[' ', ' ', ' ']]
return board
def is_win_player(board):
if board[0][0] != ' ' and board[0][1] == board[0][0] and board[0][2] == board[0][0]:
if board[0][0] == 'X':
return True
if board[1][0] != ' ' and board[1][1] == board[1][0] and board[1][2] == board[1][0]:
if board[1][0] == 'X':
return True
if board[2][0] != ' ' and board[2][1] == board[2][0] and board[2][2] == board[2][0]:
if board[2][0] == 'X':
return True
if board[0][0] != ' ' and board[1][1] == board[0][0] and board[2][2] == board[0][0]:
if board[0][0] == 'X':
return True
if board[2][0] != ' ' and board[1][1] == board[2][0] and board[0][2] == board[2][0]:
if board[2][0] == 'X':
return True
if board[0][0] != ' ' and board[1][0] == board[0][0] and board[2][0] == board[0][0]:
if board[0][0] == 'X':
return True
if board[0][1] != ' ' and board[1][1] == board[0][1] and board[2][1] == board[0][1]:
if board[0][1] == 'X':
return True
if board[0][2] != ' ' and board[1][2] == board[0][2] and board[2][2] == board[0][2]:
if board[0][2] == 'X':
return True
def is_win_ai(board):
if board[0][0] != ' ' and board[0][1] == board[0][0] and board[0][2] == board[0][0]:
if board[0][0] == 'O':
return True
if board[1][0] != ' ' and board[1][1] == board[1][0] and board[1][2] == board[1][0]:
if board[1][0] == 'O':
return True
if board[2][0] != ' ' and board[2][1] == board[2][0] and board[2][2] == board[2][0]:
if board[2][0] == 'O':
return True
if board[0][0] != ' ' and board[1][1] == board[0][0] and board[2][2] == board[0][0]:
if board[0][0] == 'O':
return True
if board[2][0] != ' ' and board[1][1] == board[2][0] and board[0][2] == board[2][0]:
if board[2][0] == 'O':
return True
if board[0][0] != ' ' and board[1][0] == board[0][0] and board[2][0] == board[0][0]:
if board[0][0] == 'O':
return True
if board[0][1] != ' ' and board[1][1] == board[0][1] and board[2][1] == board[0][1]:
if board[0][1] == 'O':
return True
if board[0][2] != ' ' and board[1][2] == board[0][2] and board[2][2] == board[0][2]:
if board[0][2] == 'O':
return True
def score_eval(board):
for row in range(0, 3):
if board[row][0] == board[row][1] and board[row][1] == board[row][2]:
if board[row][0] == 'O':
return 10
if board[row][0] == 'X':
return -10
for col in range(0, 3):
if board[0][col] == board[1][col] and board[1][col] == board[2][col]:
if board[row][0] == 'O':
return 10
if board[row][0] == 'X':
return -10
if board[0][0] == board[1][1] and board[1][1] == board[2][2]:
if board[0][0] == 'O':
return 10
if board[0][0] == 'X':
return -10
if board[2][0] == board[1][1] and board[1][1] == board[0][2]:
if board[2][0] == 'O':
return 10
if board[2][0] == 'X':
return -10
def is_tie(board):
counter = 0
for array in board:
for index in array:
if index == ' ':
counter += 1
if counter == 0:
return True
def is_terminal(board):
return is_tie(board) or is_win_player(board) or is_win_ai(board)
def minimax(board, depth, maximizingPlayer, available_positions):
valid_locations = available_positions
print(valid_locations)
terminal = is_terminal(board)
if depth == 0 or terminal:
if terminal:
if is_win_ai(board):
return None, 99999999
if is_win_player(board):
return None, -99999999
if is_tie(board):
return None, 1
else:
return None, score_eval(board)
if maximizingPlayer:
value = -inf
selection = random.choice(valid_locations)
for num in valid_locations:
board_copy = board.copy()
position = convert_position(valid_locations, num)
place_piece(board_copy, position, AI)
new_score = minimax(board_copy, depth-1, False, valid_locations)[1]
if new_score > value:
value = new_score
selection = num
return selection, value
else:
value = inf
selection = random.choice(valid_locations)
for num in valid_locations:
board_copy = board.copy()
position = convert_position(valid_locations, num)
place_piece(board_copy, position, PLAYER)
new_score = minimax(board_copy, depth-1, True, valid_locations)[1]
if new_score < value:
value = new_score
selection = num
return selection, value
while SELECTION != 'QUIT':
print('\t< Tic Tac Toe >\n')
print('\tPlease make a selection:')
print("\t'PLAY' to play a game")
print("\t'QUIT' to exit application\n")
SELECTION = input('> ').upper()
if SELECTION != 'QUIT' and SELECTION != 'PLAY':
print(SELECTION)
print('Please enter a valid selection.')
elif SELECTION == 'PLAY':
game_over = False
while not game_over:
display_board(BOARD)
if is_tie(BOARD):
print('Tie game. No winner.')
input('Press any key to continue...')
game_over = True
elif TURN == PLAYER:
print("Player's turn!")
position = int(input('Please enter a number 1 - 9 to make a mark: '))
selection = convert_position(AVAILABLE, position)
place_piece(BOARD, selection, PLAYER)
if is_win_player(BOARD):
print('Player has won the game!')
display_board(BOARD)
game_over = True
elif TURN == AI:
print("AI's turn!")
sleep(0.9)
x, y = minimax(BOARD, 7, True, AVAILABLE) #x = position, y = score
selection = convert_position(AVAILABLE, x)
place_piece(BOARD, selection, AI)
if is_win_ai(BOARD):
print('AI has won the game!')
display_board(BOARD)
game_over = True
TURN += 1
TURN = TURN % 2
print(AVAILABLE)
BOARD = clear_board(BOARD)
AVAILABLE = [1,2,3,4,5,6,7,8,9]
【问题讨论】:
-
如果您打算从事一个真正的项目,我强烈建议您首先阅读并开始关注PEP 8 - Style Guide for Python Code,以使您的代码更易于阅读和遵循——无论是为您自己还是为他人。
-
如果我运行游戏并选择
5作为我的第一个标记号码,则会出现TypeError: '>' not supported between instances of 'NoneType' and 'float'— 因为显然这是score_eval()在被调用8 次后返回的内容。这表明其中有一个代码路径超出了函数的末尾。
标签: python python-3.x minimax