用于minimax的Python n-ary树

时间:2017-10-04 16:55:40

标签: python algorithm data-structures

作为一个编码项目,我想在我已经实现的基于文本的Connect4 python游戏中为用户提供某种AI。我研究过最常用的方法,而minimax是使用的主要算法。

如果我对算法的理解是正确的,我必须实现一个7-ary树,其中每个节点都有一个板状态,并且一个玩家可以从该板状态进行所有可能移动的7个子节点。

为了实现这个树,我决定使用一个Node类,它有一个子节点列表和一个当前状态。树只有3个级别,因为根据我的理解,不需要保留整个游戏的完整日志。

节点类只是:

    class _Node(object):
    def __init__(self, state, children=[]):
        self.state = state
        self.children = children

DecisionTree类是一个添加的构造函数,它将根设置为None。

但是,我想了解方法add()如何适用于这种n-ary树。我写的代码看起来像这样:

    def add(self, state):
    if (self.root == None): 
        self.root = self._Node(state[0]) # state is a singleton list, make that state the root
    else:
        for i in range(len(self.root.children) + 1): # loop over all children of root
            curr = self.root
            while (curr.children != []): # go down in tree until we reach a leaf
                curr = curr.children
            for i in range(len(state)): # add all the new states
                curr.children.append(state[i])

我的问题是while循环,它显然无法正常工作。它从我想要的节点变成了一个列表。我想我必须索引子项,因此将索引作为参数。然而,索引一个n-ary树会变得混乱。怎么办呢?一般来说使用列表是个坏主意吗?

1 个答案:

答案 0 :(得分:1)

首先,请注意这个def __init__(..., children=[]):

如果您以这种方式初始化节点children,那么代码就像这样...

a = Node(1)
b = Node(2)
print(a.children, b.children)

a.children.append(3)
print(a.children, b.children)
print(a.children is b.children) # they both point to same object in memory.

将产生此输出:

[] []
[3] [3]
True

这种情况正在发生,因为您在构造函数中提供了空列表值,并且所有实例都共享此默认值。 换句话说,在初始化具有此[]默认子值的多个节点之后,单独节点的子节点将指向内存中的相同列表。

正确的方法是这样做:

class Node(object):
    def __init__(self, state, children=None):
        self.state = state
        self.children = children or []

首先尝试解决此问题,看看是否有帮助。

现在关于主要问题。我的意见是,你可以在这里使用列表,但是在while循环中穿越树不是 jedi-path 。我们可以在这里使用递归。

一般情况下,我无法理解为什么你需要root,但要穿越树并添加你可以做的值:

class Node(object):
    def __init__(self, state, children=None):
        self.state = state
        self.children = children or []

    def add(self, state):
        if self.children:
            for node in self.children: # loop over all children of root
                node.add(state)            # add all the new states
        else:
            self.state.extend(state) 

示例:

r = Node([3])
r.children = [Node([2]),Node([4]),Node([5])]
print(r.children[0].state)

r.add([25,14])
print(r.children[2].state)

# output will be
[2]
[5, 25, 14]