简体   繁体   English

用于极小极大的 Python n 元树

[英]Python n-ary tree for minimax

As a coding project I would like to some kind of an AI for a user to face in my already implemented text-based Connect4 python game.作为一个编码项目,我希望在我已经实现的基于文本的 Connect4 python 游戏中为用户提供某种人工智能。 I have researched the most common methods used, and minimax was the primary algorithm used.我研究了最常用的方法,minimax 是主要使用的算法。

If my understanding of the algorithm is correct, I must implement a 7-ary tree, where each node has a board state and 7 children of all possible moves one player can make from that board state.如果我对算法的理解是正确的,我必须实现一个 7 叉树,其中每个节点都有一个棋盘状态和一个玩家可以从该棋盘状态进行的所有可能移动的 7 个子节点。

For implementing this tree, I have decided to use a Node class that has a list of children Nodes and a current state.为了实现这棵树,我决定使用一个 Node 类,它有一个子节点列表和一个当前状态。 The tree will only have 3 levels, as keeping a full log of the whole game is unnecessary from my understanding.该树将只有 3 个级别,因为根据我的理解,没有必要保留整个游戏的完整日志。

The node class is simply:节点类很简单:

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

And the DecisionTree class a constructor that adds sets the root to None.而 DecisionTree 类是一个将根设置为 None 的构造函数。

However, I would like to understand how the method add() would work for an n-ary tree of this kind.但是,我想了解add()方法如何用于这种 n 叉树。 The code I wrote up looks like this:我写的代码是这样的:

    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])

My problem here is the while loop, it is obviously not working correctly.我的问题是 while 循环,它显然不能正常工作。 It goes from being a Node, as I want, to being a list.它从我想要的一个节点变成了一个列表。 I guess I'd have to index children, and therefore take in an index as a parameter.我想我必须索引孩子,因此将索引作为参数。 However, indexing an n-ary tree would get messy.但是,索引 n 元树会变得混乱。 How could this be handled?这怎么处理? Is using lists a bad idea in general?一般来说,使用列表是一个坏主意吗?

First of all, be carefull with this def __init__(..., children=[]):首先,要小心这个def __init__(..., children=[]):

If you will init your node children in that way then the code like this...如果你会以这种方式初始化你的节点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.

will produce this output:将产生这个输出:

[] []
[3] [3]
True

This is happening because you provide empty list value in constructor and this default value is shared across all instances.发生这种情况是因为您在构造函数中提供了空列表值,并且该默认值在所有实例之间共享。 In other words, after initialization several nodes with this [] default children value, children of separate nodes will point to the same list in memory.换句话说,在用这个[]默认子值初始化几个节点后,不同节点的子节点将指向内存中的同一个列表。

Correct way will be to do this like that:正确的方法是这样做:

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

Try to fix this issue first and look if that helps.尝试先解决这个问题,看看是否有帮助。

Now about the main question.现在关于主要问题。 Im my opinion, you can use lists here, but travelling through tree with while loop is not jedi-path .我认为,您可以在此处使用列表,但使用 while 循环遍历树不是jedi-path We can use recursion here.我们可以在这里使用递归。

In general i can't understand why you need root here, but to travel across tree and add values you can do following:一般来说,我不明白为什么你需要 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) 

Example:例子:

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]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM