简体   繁体   中英

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. I have researched the most common methods used, and minimax was the primary algorithm used.

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.

For implementing this tree, I have decided to use a Node class that has a list of children Nodes and a current state. The tree will only have 3 levels, as keeping a full log of the whole game is unnecessary from my understanding.

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.

However, I would like to understand how the method add() would work for an n-ary tree of this kind. 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. 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. How could this be handled? Is using lists a bad idea in general?

First of all, be carefull with this def __init__(..., children=[]):

If you will init your node children in that way then the code like this...

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 . 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:

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]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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