I’m trying to learn the minimax algorithm. my minimax algorithm just doesn’t work, The computer just plays “O” in the next available square. My entire source code is below (sorry for the wall of text). The bestScore variable stays at what it was initially set as (1000 or -1000 depending on if it was maximising or minimising) and it never returns one of the base cases. Not sure where to go from here
from json.encoder import INFINITY
from itertools import combinations
from pygame.examples import grid
class GameState():
def __init__(self):
self.grid = [["-","-","-"],
["-","-","-"],
["-","-","-"]]
self.MagicSquare = [[4, 9, 2],
[3, 5, 7],
[8, 1, 6]]
self.XtoMove = True
self.gameOver = False
self.Xsum = []
self.Osum = []
self.Xwins = False
self.Owins = False
self.draw = False
def makeMove(self, row, col):
totalX = 0
totalO = 0
if self.grid[row][col] == "-":
if self.XtoMove == True:
self.grid[row][col] = 'X'
self.bestMove()
#self.XtoMove = False
self.Xsum.append(self.MagicSquare[row][col])
for combo in combinations(self.Xsum, 3):
if sum(combo) == 15:
self.gameOver = True
self.Xwins = True
if len(self.Xsum) + len(self.Osum) == 9:
self.gameOver = True
self.draw = True
def checkDraw(self):
if len(self.Xsum) + len(self.Osum) == 9:
self.gameOver = True
self.draw = True
return True
def checkWinner(self, player):
if player == 'X':
sums = self.Xsum
else:
sums = self.Osum
for combo in combinations(sums, 3):
if sum(combo) == 15:
return True
return False
def minimax(self, grid, depth, isMaximising):
if self.checkWinner("O"):
return 1
elif self.checkWinner("X"):
return -1
elif self.checkDraw():
return 0
if isMaximising:
bestScore = -1000
for r in range(3):
for c in range(3):
if grid[r][c] == "-":
grid[r][c] = 'O'
score = self.minimax(grid, depth + 1, False)
grid[r][c] = "-"
bestScore = max(score, bestScore)
return bestScore
else:
bestScore = 1000
for r in range(3):
for c in range(3):
if grid[r][c] == "-":
grid[r][c] = 'X'
score = self.minimax(grid, depth + 1, True)
grid[r][c] = "-"
bestScore = min(score, bestScore)
return bestScore
def bestMove(self):
bestScore = -10000
move = (-1, -1)
for r in range(3):
for c in range(3):
if self.grid[r][c] == "-":
self.grid[r][c] = 'O'
score = self.minimax(self.grid, 0, False)
self.grid[r][c] = "-"
if score > bestScore:
bestScore = score
move = (r, c)
if move != (-1,-1):
self.grid[move[0]][move[1]] = 'O'
self.Osum.append(self.MagicSquare[move[0]][move[1]])
for combo in combinations(self.Osum, 3):
if sum(combo) == 15:
self.gameOver = True
self.Owins = True
if len(self.Xsum) + len(self.Osum) == 9 and not self.Owins:
self.gameOver = True
self.draw = True
2
The minimax
function uses grid from an argument but bestMove
uses self.grid
. It’s this lack of synchronicity that I believe may be causing your problem. I think it’s that self.grid
isn’t being updated and instead just the argument grid
is which then does not follow through.
I hope this helps.
3