0

我创建了一个新类,它代表井字游戏中的一个位置。基本上我要做的是制作一个包含所有可能的游戏位置的树,其中每个节点都是一个Position对象,并使用极小极大算法为玩家找到最佳移动。minimax 算法未在下面显示,因为 Position 类未按要求工作。

该类Position有一个generate_children方法可以列出Position可以从当前位置到达的对象。执行程序,我们得到输出,每次迭代后pos_matrix,当前Position对象的值都在变化,这是不希望的。我没有触及pos_matrix循环中当前位置对象的 ,并play_move制作了矩阵的副本以避免弄乱它。仍然在pos_matrix改变每次迭代。

怎么了?我该如何调试它?

试过:搬出play_move课堂,没用。

注意0pos_matrix中的A代表空方格,1代表“X”,-1代表“O”。
kiska_chance意味着“谁的机会”。:P

class Position:
    def __init__(self, parent_):
        self.parent = parent_
        self.children = []
        self.best_move = []
        self.pos_matrix = []
        self.last_move = []

    def set_pos_matrix(self, pos_matrix_):
        self.pos_matrix = list(pos_matrix_)
        # Avoiding copying problems by creating copy of list

    def set_last_move(self, last_move_):
        self.last_move = list(last_move_)
        # Avoiding copying problems by creating copy of list

    def play_move(self, move, kiska_chance):
        m2 = list(self.pos_matrix)
        x, y = move
        m2[x][y] = kiska_chance

        return m2

    def generate_children(self, kiska_chance):
        children_ = []
        for move in self.get_possible_moves():
            # Passing a Position object into the possible moves with
            # parent as self.
            pos_temp = Position(self)
            pos_temp.set_pos_matrix(self.play_move(move, kiska_chance))
            pos_temp.set_last_move(move)

            print self.pos_matrix

            children_.append(pos_temp)
        self.children = children_

        return children_

    def get_possible_moves(self):
        dem_moves = []
        for i in xrange(3):
            for j in xrange(3):
                if self.pos_matrix[i][j]==0:
                    dem_moves.append([i, j])
        return dem_moves


pos = Position(None)
pos.set_pos_matrix([[0, 0, 0],
                    [0, 0, 0],
                    [0, 0, 0]])
pos.generate_children(1)
4

2 回答 2

1

您在self.pos_matrix. 您只是在复制外部列表。因此,列表中的所有列表仍然由两个列表共享。您需要复制列表中的列表。请参阅更正的代码:

def play_move(self, move, kiska_chance):
    m2 = list(list(l) for l in self.pos_matrix)
    x, y = move
    m2[x][y] = kiska_chance

    return m2

也在:

def set_pos_matrix(self, pos_matrix_):
    self.pos_matrix = list(list(l) for l in pos_matrix_)
    # Avoiding copying problems by creating copy of list and lists in list
于 2015-09-01T03:31:33.947 回答
1

通常,您必须为此使用deepcopy,因为lists它们是mutable对象,它们将通过引用传递给其他对象。

mutable让我们看看同时包含和immutable对象的列表会发生什么。

>>> l1 = [1, 2]
>>> l2 = [3, 4]
>>> t1 = (1, 2, 3)
>>> l = [l1, l2, t1, 5]
>>> l
[[1, 2], [3, 4], (1, 2, 3), 5]

这里list l是有l1 and l2,然后tuple t1是一个数字5,所以list是一个mutable对象和数字,tuples而不是。

如果您只是简单地 list(l)将其变为shallow copy,则浅拷贝意味着仅复制非常外部的对象,但您的内部对象仍然引用相同的对象。

您最好copy为此使用模块。

import copy
>>> l_copy = copy.copy(l)

现在我们在这里做了一个shallow copy......让我们看看会发生什么。

>>> l_copy
[[1, 2], [3, 4], (1, 2, 3), 5]

我们有 gt 相同的列表l,让我们尝试将一个值附加到inner list.

>>> l_copy[0]
[1, 2]
>>> l_copy[0].append(0)
>>> l_copy
[[1, 2, 0], [3, 4], (1, 2, 3), 5]

现在 l[0] --> [1, 2] 又增加了一个值 [1,2, 0] ..如果您尝试检查ll1您也可以在那里看到相同的值。

>>> l
[[1, 2, 0], [3, 4], (1, 2, 3), 5]
>>> l1
[1, 2, 0]

你没有修改l and l1,但他们仍然获得了新的价值0,如果你的mutable对象会发生这种情况。

让我们在这里尝试deepcopy.. 注意:您必须l1, l2 and l再次定义不要使用旧的..

>>> l_copy = copy.deepcopy(l)
>>> l_copy
[[1, 2], [3, 4], (1, 2, 3), 5]

现在将值附加到l_copy[0]这意味着l1..

>>> l_copy[0].append(0)
>>> l_copy
[[1, 2, 0], [3, 4], (1, 2, 3), 5]

并尝试检查l1 and l..

>>> l
[[1, 2], [3, 4], (1, 2, 3), 5]
>>> l1
[1, 2]

如果您现在看到该值正在not反映l1 and l

因此,您必须小心处理mutable对象。并且可以参考下面的文档以获取有关copyand的更多信息deepcopy

https://docs.python.org/2/library/copy.html

于 2015-09-01T03:57:00.437 回答