所以我很长一段时间以来一直在研究这个问题。但是我只是想不通。
我有一个像这样的球员课:
class perfectplayer():
def __init__(self, player, game):
self.player = player
self.game = game
def possible_moves(self, board):
'''Finds all possible moves of given board'''
possible_moves = []
for x in range(len(board)):
for y in range(len(board[x])):
if board[x][y] is None:
possible_moves.append((x, y))
return possible_moves
def score(self, game, depth):
'''Gives score to given board based on depth and who wins'''
if game.win()[0]:
if game.win()[1] is self.player:
return 10 - depth
else:
return depth - 10
return 0
def minimax(self, game, depth):
'''Constructs minimax tree and selects best move based on that tree'''
if game.game_over():
return self.score(game, depth)
depth += 1
scores = []
moves = []
# Recursively creates tree of possible decisions
for move in self.possible_moves(game.board):
possible_game = game
possible_game.move(move)
scores.append(self.minimax(possible_game, depth))
moves.append(move)
# max the score if it is player's turn
if game.current_player is self.player:
max_score_idx = scores.index(max(scores))
self.choice = moves[max_score_idx]
return scores[max_score_idx]
# min the score if it is not player's turn
else:
min_score_idx = scores.index(min(scores))
self.choice = moves[min_score_idx]
return scores[min_score_idx]
def best_move(self, game):
'''returns best move in give game state'''
self.minimax(game, 0)
return self.choice
哪个游戏类具有正确运行所需的所有功能。如果游戏结束,谁赢得了比赛以及谁将要前进,它可以返回。正如我测试过的那样,所有这些都有效。想法基本上是,best_move函数返回AI播放器的下一个选择。但是当我运行我的小游戏时:
game1 = game()
player1 = perfectplayer("x", game1)
while not game1.game_over():
# finds best choice
choice = player1.best_move(game1)
# puts down a mark
game1.move(choice)
# renders game
game1.render()
move_x = int(input("please input row: "))
move_y = int(input("please input column: "))
game1.move((move_x, move_y))
if game1.win()[0]:
print(game1.win()[1], "has won!")
我得到以下输出:
>> o|o|x|
o|x|o|
x|o|x|
>> please input row: 1
>> please input column: 1
>> x has won!
因此,它正确地知道x赢了并且正确地要求我输入,但是为什么我的游戏板在1圈后就被填满了?这在我的代码中哪里发生?选择变量是正确的,因为它始终是两个坐标的元组。
伪代码来自以下网站:https://www.neverstopbuilding.com/blog/minimax
这是游戏类的代码:
class game():
def __init__(self, board=None, starting_player="x"):
if board is None:
self.board = [[None, None, None],
[None, None, None],
[None, None, None]]
else:
self.board = board
self.current_player = starting_player
def render(self):
for row in self.board:
for item in row:
if item is None:
print(".", end="|")
else:
print(item, end="|")
print()
def move(self, move):
move_x = move[0]
move_y = move[1]
self.board[move_x][move_y] = self.current_player
self.switch()
def legalmove(self, move):
move_x = move[0]
move_y = move[1]
if self.board[move_x][move_y] is None:
return True
return False
def switch(self):
if self.current_player == "x":
self.current_player = "o"
else:
self.current_player = "x"
def win(self):
board = self.board
for x in range(len(board)):
for y in range(len(board[x])):
if board[0][y] == board[1][y] == board[2][y] is not None:
return True, board[0][y]
if board[x][0] == board[x][1] == board[x][2] is not None:
return True, board[x][0]
if x == y and board[0][0] == board[1][1] == board[2][2] is not None:
return True, board[0][0]
if x + y == 2 and board[0][2] == board[1][1] == board[2][0] is not None:
return True, board[0][2]
return False, None
def game_over(self):
for x in range(len(self.board)):
for y in range(len(self.board[x])):
if self.board[x][y] is None:
return False
return True
答案 0 :(得分:3)
我认为问题在于这一行:
possible_game = game
不是不是创建游戏状态的副本,而只是创建它的另一个引用。因此,您的搜索会修改实际的面板。要解决此问题,您可以: