Reputation: 29
I'm having a hard time understanding the recursive part of the minimax Algorithm.
def minimax(state, depth, player):
if player == MAX:
best = [-1, -1, -infinity]
else:
best = [-1, -1, +infinity]
if depth == 0 or game_over(state):
score = evaluate(state)
return [-1, -1, score]
for cell in empty_cells(state):
x, y = cell[0], cell[1]
state[x][y] = player
score = minimax(state, depth - 1, -player)
state[x][y] = 0
score[0], score[1] = x, y
if player == MAX:
if score[2] > best[2]:
best = score
else:
if score[2] < best[2]:
best = score
return best
for example this code. when the function calls itself inside the loop, the loop keeps going to state[x][y] = 0
? what's stooping the function? or what actions the recursive part of the function does?
tnx
Upvotes: 1
Views: 145
Reputation: 8180
You have recursive function, that is a function that calls itself with (hopefully) different arguments. The question is: how do we prove that such a function ever stops? The generic proof is a proof by induction: let n
be an argument of the function f
. If you can show that:
f(0)
is definedf(n)
are always of type f(k)
where 0 <= k < n
You have a proof by induction (strong version) that f(n)
is defined for every n >= 0
.
In your function, depth
is a good candidate for n
. But len(empty_cells(state))
too. Look at the two statements that surround the recursive call:
state[x][y] = player
...
state[x][y] = 0
This is a common technique: you update the state before the call, and restore the state after the call (assumption: a cell (x, y)
is empty if state[x][y] == 0
). Hence, the number of empty cells of the recursive call is lower than the current number of empty cells.
And you might have a game_over
state.
Without additional information, it is impossible to say what will stop the recursive calls: depth
reaches 0
, there's a game_over
or there are no empty cells left.
Note that depth
might be negative at the beginning, game_over
might never occur, but it is certain that the function will stop when the number of empty cells is 0
(if it has not stopped before).
I think you're having a hard time understanding this piece of code because the score
variable is sometimes a number, sometimes a 3 elements list (and should probably be a tuple in this case).
Furthermore, the stop condition could be at the beginning of the function.
This version should be clearer because it hides the behavior variations caused by +/-player
:
def minimax(state, depth, player):
if depth == 0 or game_over(state):
score = evaluate(state)
return [-1, -1, score]
best = [-1, -1, initial_score(player)]
for x, y in empty_cells(state):
state[x][y] = player # fill this cell
_, _, score = minimax(state, depth - 1, -player) # extract the score
cur = [x, y, score]
state[x][y] = 0 # restore state
if is_better(player, cur, best):
best = cur
return best
def initial_score(player):
if player == MAX:
return -infinity
else
return +infinity
def is_better(player, first, second):
if player == MAX:
return first[2] > second[2]
else:
return first[2] < second[2]
Much could be rewritten, but we're not https://codereview.stackexchange.com...
Upvotes: 2