如何在递归函数中实现一个值?

时间:2018-02-24 15:34:56

标签: python recursion minimax nim-game

我尝试用Python编写minimax nim游戏。我差不多完成了代码。但是,我无法解决一个棘手的问题。我无法达到最佳运动'算法。我从(5,Max)位置开始,算法输出应为(4,Min)。我的算法使用实用值来解决整个树,但无法恢复到最佳运动。

def startposition():
    return 5, 'max'


def terminalstate(state):
    if state == (0, 'min') or state == (0, 'max'):
        return True
    else:
        return False


def minimax(state):
    turn,heap=state
    if terminalstate(state):
        return utilitystatic(state)
    else:
        if heap == 'min':
            value = 250
            for x in successorsgenerator(state):
                value = min(value, minimax(x))
            result = state, value
        elif heap == 'max':
            value = -250
            for x in successorsgenerator(state):
                value = max(value, minimax(x))
            result = state, value

        print(result)
    return value


def utilitystatic(state):
    turn, heap = state
    assert terminalstate(state)
    if state[1] == 'max':
        return -100
    elif state[1] == 'min':
        return 100
    assert False


def successorsgenerator(state):
    successors = []
    state = toggle(state)
    newstate = decrease(state)
    i = 0
    while newstate[0] >= 0 and i < 3:
        successors.append(newstate)
        i += 1
        newstate = decrease(newstate)
    print('successors:', successors)
    return successors


def toggle(state):
    state = list(state)
    state[1] = 'min' if state[1] == 'max' else 'max'
    state = tuple(state)
    return state


def decrease(state):
    state = state[:0] + (state[0] - 1,) + state[1:2]
    return state


stick = startposition()
result = minimax(stick)
print('result:', result)

2 个答案:

答案 0 :(得分:1)

如果您不想将整个移动序列存储在内存中(通常/通常是不必要的),请从生成当前游戏状态的可能子项开始。不要在当前状态下运行minimax,只需找到可能的下一步动作。让我们想象一下你可以从哪里移动(A,B,C)。现在在A上运行minimax算法并存储结果以及移动A的描述。对B和C重复。现在你应该有类似的东西:

A: 3.5
B: 1.2
C: -7.1

请记住,这些不是游戏状态的启发式值,这些值是由采取这些操作立即产生的。从最大化玩家的角度来看,它们代表了当前玩家选择该移动时其他玩家可以强制当前玩家在未来接收的最小值。

在这个例子中,移动A对于最大化玩家来说是最好的,移动C对于最小化玩家来说是最好的。

答案 1 :(得分:0)

DependencyService.Get<>()中,您目前只找到继承状态的最佳(最小值或最大值取决于玩家)值,但尚未准确记住哪个后继状态在每个深度级别都是最佳状态。如果您不将这些信息存储在内存中,您将无法确定哪个移动最佳。所以,你想尝试类似的东西:

minimax()

通过一些小的更改,我们现在存储导致def minimax(state): turn,heap=state if terminalstate(state): return utilitystatic(state), _ else: if heap == 'min': value = 250 best_succ = None for x in successorsgenerator(state): val, _ = minimax(x) if val < value: value = val best_succ = x result = state, value elif heap == 'max': value = -250 best_succ = None for x in successorsgenerator(state): val, _ = minimax(x) if val > value: value = val best_succ = x result = state, value print(result) return value, best_succ 中最佳价值的后继x,因此也能够准确地告诉哪个继承者是最好的(而不仅仅是能说出它的价值是什么)