I'm trying solve N Puzzle with Depth First Search using python 3.
With 3 x 3 puzzle it run good and fast but with 4 x 4 puzzle, it runs too slow and can't find solution with error: "MemoryError".
I also use "h(n) = depth + number of wrong tiles" to evaluate priority of each node.
I'm a newbie to python so hope you can help me with this
Here is my code:
import sys
import getopt
import random
import time
class State:
def __init__(self, parent, board, move, depth):
self.parent = parent
self.previousMove = move
self.board = board
self.map = ''.join(str(e) for e in board)
self.depth = depth
self.cost = self.calculateCost()
def calculateCost(self):
pos = 1
count = 0
for tile in self.board:
if tile == pos:
count += 1
pos += 1
return self.depth + 8 - count
class Puzzle:
def __init__(self, k, customBoard = None):
self.k = k
self.n = k*k - 1
self.sizeOfBoard = k*k
self.timeOfSolving = 0
self.timeOfGenerateSuccessors = 0
self.maxDeepSearch = 0
self.inititalState = State(None, self.createInitialBoard(customBoard), 'Start', 0)
self.goalBoard = self.createGoalBoard()
self.finalState = None
self.stateStorage = set() # Store states that have visited
self.path = [] # Store states that lead to goalstate
self.stack = []
def isSolvable(self, board):
# count invertion in puzzle's board
invCount = 0
for i in range(0, self.sizeOfBoard - 1):
if board[i] == 0:
continue
for j in range(i+1, self.sizeOfBoard):
if board[j] == 0:
continue
if board[i] > board[j]:
invCount += 1
# print(invCount)
if (invCount % 2 == 0):
return True
return False
def createInitialBoard(self, customBoard):
print("Creating initial state")
if customBoard is None:
board = []
lstAddSuccess = []
while 1:
board.clear()
lstAddSuccess.clear()
for count in range(0, self.k*self.k):
newTile = random.randint(0, self.n)
while newTile in lstAddSuccess:
newTile = random.randint(0, self.n)
lstAddSuccess += [newTile]
board += [newTile]
if self.isSolvable(board):
break
else:
board = [int(e) for e in customBoard]
if not self.isSolvable(board):
print("Cant find solution with this puzzle! Exiting...")
exit(-1)
return board
def createGoalBoard(self):
board = []
for count in range(1, self.n + 1):
board += [count]
board += [0]
return board
def printBoard(self, board):
for row in range(0, self.sizeOfBoard, self.k):
# for col in range(row, row + self.k):
print(board[row:row + self.k])
def generateSuccessors(self, currentState):
indexOfZero = currentState.board.index(0)
rowIndexOfZero = indexOfZero % self.k
colIndexOfZero = indexOfZero // self.k
lstSuccessors = []
# Slide to zero to up
if colIndexOfZero != 0:
newState = currentState.board.copy()
newState[indexOfZero] = newState[indexOfZero - self.k]
newState[indexOfZero - self.k] = 0
lstSuccessors.append(
State(currentState, newState, 'up', currentState.depth + 1))
# Slide zero to down
if colIndexOfZero != self.k - 1:
newState = currentState.board.copy()
newState[indexOfZero] = newState[indexOfZero + self.k]
newState[indexOfZero + self.k] = 0
lstSuccessors.append(
State(currentState, newState, 'down', currentState.depth + 1))
# slide zero to left
if rowIndexOfZero != 0:
newState = currentState.board.copy()
newState[indexOfZero] = newState[indexOfZero - 1]
newState[indexOfZero - 1] = 0
lstSuccessors.append(
State(currentState, newState, 'left', currentState.depth + 1))
# Slide zero to right
if rowIndexOfZero != self.k - 1:
newState = currentState.board.copy()
newState[indexOfZero] = newState[indexOfZero + 1]
newState[indexOfZero + 1] = 0
lstSuccessors.append(
State(currentState, newState, 'right', currentState.depth + 1))
lstSuccessorsCost = [ele.cost for ele in lstSuccessors]
lstSuccessorsInOrderOfCost = []
for i in range(0, len(lstSuccessorsCost)):
lstSuccessorsInOrderOfCost.append(lstSuccessors[lstSuccessorsCost.index(min(lstSuccessorsCost))])
lstSuccessorsCost[lstSuccessorsCost.index(min(lstSuccessorsCost))] = 100
return lstSuccessorsInOrderOfCost
def solvePuzzle(self, currentState):
self.stack.append(currentState)
self.stateStorage.add(currentState.map)
while len(self.stack) > 0:
currentState = self.stack.pop()
if currentState.board == self.goalBoard:
# find path
# self.printBoard(currentState.board)
self.finalState = currentState
print("Solving " + str(self.n) + " puzzle done!")
return
start_time_gen = time.time()
lstSuccessor = self.generateSuccessors(currentState)
end_time_gen = time.time()
timeOfGen = end_time_gen - start_time_gen
self.timeOfGenerateSuccessors += timeOfGen
for successor in lstSuccessor[::-1]:
if successor.map not in self.stateStorage:
self.stack.append(successor)
self.stateStorage.add(successor.map)
if successor.depth > self.maxDeepSearch:
self.maxDeepSearch += 1
print("Cant solve puzzle! Exiting...")
exit(-1)
def solve(self):
start_time = time.time()
self.solvePuzzle(self.inititalState)
end_time = time.time()
self.timeOfSolving = end_time - start_time
print("Running time: " + str(self.timeOfSolving))
print("Max Search Dept: " + str(self.maxDeepSearch))
print("Final State Dept: " + str(self.finalState.depth))
def printInitialBoard(self):
self.printBoard(self.inititalState.board)
def printPath(self):
if self.finalState is None:
print("No solution found!")
return
path = []
state = self.finalState
while (state is not None):
if state.previousMove is not None:
path.append(state.previousMove)
state = state.parent
print("path: "),
print(path[::-1])
def main(argv):
# if (len(argv) != 1 or int(argv[0]) not in range(1, 10000)):
# print("Input must be k of integer, which is k*k matrix of puzzle")
# exit()
# eight_puzzle = Puzzle(int(argv[0]))
k = int(input("Enter size of k * k puzzle, k = "))
while k not in range(2, 100):
print("k must be in range 2 - 100")
k = int(input("Enter size of k * k puzzle, k = "))
print("""
Choose:
1. Randome puzzle
2. Custome puzzle
""")
file = input()
if int(file) == 1:
puzzle = Puzzle(k)
elif int(file) == 2:
board = input("Enter puzzle: ")
puzzle = Puzzle(k ,list(board.split(" ")))
puzzle.printInitialBoard()
puzzle.solve()
puzzle.printPath()
if __name__ == "__main__":
main(sys.argv[1:])
Related
Here is my brief: 'Nimsticks is a turn-taking zero-sum game for two players. The game state consists of one or more piles of sticks. On their turn, a player may take 1, 2 or 3 sticks from any one pile. The player who takes the last stick is the loser of the game.
The problem is my code works fine when there is only one pile ([4], 1) but if I run it with multiple piles ([2, 3], 1) the if statements maxValue < v and minValue > v aren’t triggered (which they always should be due to inf) and are causing an error. Please help!
import copy
import math
def minimax_value(state):
if (state[0] == []):
return(result(state))
else:
if (state[1] == 1):
v, path = (max_value(state))
else:
v, path = (min_value(state))
optimalPath = path
optimalPath.append(state)
optimalPath.reverse()
print('Example play: ' + str(optimalPath))
return str(v)
def terminal(state):
if (state[0] == []):
return True
else:
return False
def utility(state):
if (state[1] == 1):
return(1, [])
else:
return(-1, [])
def max_value(state):
if terminal(state):
return(utility(state))
else:
v = -1 * math.inf
for c in next_states(state):
minValue, minPath = min_value(c)
if (minValue > v):
v = minValue
bestPath = minPath.copy()
bestSucc = c
bestPath.append(bestSucc)
return(v, bestPath)
def min_value(state):
if terminal(state):
return(utility(state))
else:
v = 1 * math.inf
for c in next_states(state):
maxValue, maxPath = max_value(c)
if (maxValue < v):
v = maxValue
bestPath = maxPath.copy()
bestSucc = c
bestPath.append(bestSucc)
return(v, bestPath)
def next_states(state):
player = state[1]
piles = copy.deepcopy(state[0])
pilesSave = copy.deepcopy(piles)
temp = []
newList = []
for x in range(0, len(piles)):
for y in range(1, 4):
piles[x] = piles[x] - y
if (piles[x] >= 0):
temp = copy.deepcopy(piles)
if (piles[x] == 0):
del temp[x]
newList.append(temp)
break
newList.append(temp)
piles[x] = pilesSave[x]
newList2 = []
for item in newList:
if (player == 1):
toAdd = (item, 2)
else:
toAdd = (item, 1)
newList2.append(toAdd)
return(newList2)
print(minimax_value(([2, 3], 1)))
I am trying to make a sudoku solver that solves boards very quickly. At the moment my solver works on easy boards but never terminates on harder boards. I believe it has something to do with my recursion because easy boards do not require recursion and hard boards do. Any help is appreciated.
import sys
def rowno(i):
return i // 9
def colno(i):
return i % 9
def boxno(i):
return (i // 9 // 3 )*3 + (i // 3) % 3
def isNeighbor(i, j):
if rowno(i) == rowno(j) or colno(i) == colno(j) or boxno(i) == boxno(j):
return True
else:
return False
def getFileName():
if sys.platform == "win32":
filename = input("Filename? ")
else:
filename = sys.argv[-1]
return filename
solutionlist = []
class Board(object):
def __init__(self, puzzle):
self.puzzle = puzzle
self.board = [Cell(int(value), idx) for idx, value in enumerate(puzzle)]
self.change = False
def printAll(self):
print [cell.candidates for cell in self.board]
#return str(" ")
def update(self):
self.change = False
l = [cell for cell in self.board if len(cell.candidates) == 1]
for i in l:
for j in xrange(81):
if isNeighbor(i.dex, j) and i.dex != j:
old = self.board[j].candidates
self.board[j].delCandidate(i.value)
if len(old) != len(self.board[j].candidates):
self.change = True
def toString(self):
str1 = ''.join(str(e.value) for e in self.board)
return str1
def solved(self):
for cell in self.board:
if len(cell.candidates) != 1:
return False
return True
def solve(self):
self.change = True
while self.change == True:
self.update()
if self.solved():
solutionlist.append(self.board)
return
l = [cell for cell in self.board if len(cell.candidates) > 1]
for i in l:
for j in i.candidates:
newBoard = Board(self.toString())
curLen = 12
curCell = -1
for u in l:
if len(u.candidates)<curLen:
curLen=len(u.candidates)
curCell = u.dex
for c in newBoard.board[curCell].candidates:
newBoard.board[curCell].candidates = [int(c)]
newBoard.board[curCell].value = int(c)
newBoard.solve()
return
def __repr__(self):
l = [cell.value for cell in self.board]
return str(l)
class Cell(object):
def __init__(self, value, dex):
self.value = value
self.dex = dex
if value == 0:
self.candidates = [1,2,3,4,5,6,7,8,9]
else:
self.candidates = [int(value)]
def __str__(self):
return str(self.value)
def delCandidate(self, value):
# deletes value from candidate list
#return self.candidate.remove(value);
self.candidates = [x for x in self.candidates if x != value]
if len(self.candidates) == 1:
self.value = self.candidates[0]
easy = "700583006006001405052006083300200958500078060648010300060802500003150072215600030"
twosol = "000805200800000401705040009000100702040000000006430000030900000010006080000000000"
hard = "040090008000000070060000120030020000005839060080600700050170600000043000003000200"
#easy solution: 794583216836721495152496783371264958529378164648915327967832541483159672215647839
b = Board(hard)
print b
b.solve()
print "end of the line"
for i in solutionlist:
print [cell.value for cell in i]
print "\n"
One major issue is the line for i in l: in the solve method. Since you're recursing, you only need to fill in one cell - the recursion will take care of the rest. So instead of for i in l:, just recurse on the one cell that is the best candidate (curCell):
l = [cell for cell in self.board if len(cell.candidates) > 1]
if len(l) > 0:
newBoard = Board(self.toString())
curLen = 12
curCell = -1
for u in l:
if len(u.candidates)<curLen:
curLen=len(u.candidates)
curCell = u.dex
for c in newBoard.board[curCell].candidates:
newBoard.board[curCell].candidates = [int(c)]
newBoard.board[curCell].value = int(c)
newBoard.solve()
I'm trying to solve the Botclean problem on Hackerrank:
https://www.hackerrank.com/challenges/botclean
The solution I came up with will scan the board for the dirty tile with the shortest distance then navigate to it, clean it, and repeat until it's all clean.
Code:
nextD = []
def next_move(posr, posc, board):
global nextD
if nextD == []:
nextD = next_d(posr,posc,board)
if (nextD[0] == posr) and (nextD[1] == posc):
print("CLEAN")
board[posr][posc] = "-"
nextD = []
return
if posc < nextD[1]:
print("RIGHT")
return
#posc += 1
elif posc > nextD[1]:
print("LEFT")
return
#posc -= 1
if posr < nextD[0]:
print("DOWN")
return
#posr += 1
elif posr > nextD[0]:
print("UP")
return
#posr -= 1
#find closest d
def next_d(posr, posc, board):
arr = []
for i in range(len(board)):
try:
#print("Distance to: ", i, board[i].index('d'), abs(i-posc) + abs(board[i].index('d')))
vals = [abs(i-posr) + abs(board[i].index('d')-posc), i, board[i].index('d')]
arr.append(vals)
except ValueError:
pass
arr.sort()
return [arr[0][1], arr[0][2]]
# Tail starts here
if __name__ == "__main__":
pos = [int(i) for i in input().strip().split()]
board = [[j for j in input().strip()] for i in range(5)]
next_move(pos[0], pos[1], board)
I'm stuck at 17.60/17.82. My bot gets 16, 20, 34, 26 on the test cases. The best scores are 16, 25, 28 and 18. The discussion says to implement a greedy algorithm though I'm not entirely sure how in this context. Any suggestions for optimizing this problem? Did I go about it completely wrong?
edit: Time isn't a criteria. So scanning the board repeatedly isn't necessarily a problem.
If you want to watch it in action:
https://www.hackerrank.com/showgame/4843664
Thank you!
Got it
nextD = []
def next_move(posr, posc, board):
global nextD
if nextD == []:
nextD = next_d(posr,posc,board)
if (nextD[0] == posr) and (nextD[1] == posc):
print("CLEAN")
board[posr][posc] = "-"
nextD = []
elif posc < nextD[1]:
print("RIGHT")
elif posc > nextD[1]:
print("LEFT")
elif posr < nextD[0]:
print("DOWN")
elif posr > nextD[0]:
print("UP")
#find closest d
def next_d(posr, posc, board):
val = len(board) * 2
nextD = []
for i in range(len(board)):
for j in range(len(board[i])):
if board[i][j] == 'd' and abs(i - posr) + abs(j - posc) < val:
val = abs(i - posr) + abs(j - posc)
nextD = [i, j]
return nextD
# Tail starts here
if __name__ == "__main__":
pos = [int(i) for i in input().strip().split()]
board = [[j for j in input().strip()] for i in range(5)]
next_move(pos[0], pos[1], board)
I have implemented a simple genetic algorithm in python - here is the most of the code:
import random
ings = (('w1', 200, 25, 80),
('su1', 50, 55, 150),
('su2', 400, 100, 203),
('sy1', 10, 150, 355),
('sy2', 123, 88, 101),
('sy3', 225, 5, 30),
('sy4', 1, 44, 99),
('sy5', 500, 220, 300))
mutationRate = 0.2
crossoverRate = 0.9
iterations = 100
file = open('D:\\logfile2.txt', 'a')
class Ingredient:
def __init__(self, n, p, mi, ma):
self.name = n
self.price = p
self.min = mi
self.max = ma
self.perc = random.randrange(self.min, self.max)
class Drink:
def __init__(self):
self.ing = [Ingredient(*x) for x in ings]
self.normalize()
self.fitness = self.evaluate()
def normalize(self):
sum = 0
for x in self.ing:
sum += x.perc
if sum < 1000:
offset = 1000 - sum
while not offset == 0:
index = random.randrange(len(self.ing))
val = self.ing[index].max - self.ing[index].perc
threshold = random.randrange(val) if val > 0 else 0
threshold = threshold if threshold < offset else offset
self.ing[index].perc += threshold
offset -= threshold
if sum > 1000:
offset = sum - 1000
while not offset == 0:
index = random.randrange(len(self.ing))
val = self.ing[index].perc - self.ing[index].min
threshold = random.randrange(val) if val > 0 else 0
threshold = threshold if threshold < offset else offset
self.ing[index].perc -= threshold
offset -= threshold
def evaluate(self):
fitness = 0
for x in self.ing:
fitness += x.perc * x.price
return 300000 - fitness
class GeneticAlgorithm:
def __init__(self):
self.drinkList = [Drink() for x in range(8)]
self.pool = []
def mutate(self, index):
ing1, ing2 = random.randrange(8), random.randrange(8)
while ing1 == ing2:
ing2 = random.randrange(8)
ptr = self.drinkList[index].ing
ing1thr = ptr[ing1].max - ptr[ing1].perc
ing2thr = ptr[ing2].perc - ptr[ing2].min
if ing1thr & ing2thr:
change = random.randrange(ing1thr if ing1thr < ing2thr else ing2thr)
ptr[ing1].perc += change
ptr[ing2].perc -= change
def crossover(self, index1, index2):
ing1, ing2 = random.randrange(8), random.randrange(8)
while ing1 == ing2:
ing2 = random.randrange(8)
ptr1 = self.drinkList[index1].ing[:]
ptr2 = self.drinkList[index2].ing[:]
resultIndex1 = random.randrange(len(self.drinkList))
while True:
resultIndex2 = random.randrange(len(self.drinkList))
if not resultIndex1 == resultIndex2:
break
bias = 1 if ptr1[ing1].perc > ptr2[ing1].perc else -1
if bias == 1:
maxChange = min(ptr1[ing1].perc - ptr1[ing1].min,
ptr1[ing2].max - ptr1[ing2].perc,
ptr2[ing1].max - ptr2[ing1].perc,
ptr2[ing2].perc - ptr2[ing2].min)
if maxChange:
change = random.randrange(maxChange)
ptr1[ing1].perc -= change
ptr1[ing2].perc += change
ptr2[ing1].perc += change
ptr2[ing2].perc -= change
self.drinkList[resultIndex1].ing = ptr1[:]
self.drinkList[resultIndex2].ing = ptr2[:]
if bias == -1:
maxChange = min(ptr1[ing1].max - ptr1[ing1].perc,
ptr1[ing2].perc - ptr1[ing2].min,
ptr2[ing1].perc - ptr2[ing1].min,
ptr2[ing2].max - ptr2[ing2].perc)
if maxChange:
change = random.randrange(maxChange)
ptr1[ing1].perc += change
ptr1[ing2].perc -= change
ptr2[ing1].perc -= change
ptr2[ing2].perc += change
self.drinkList[resultIndex1].ing = ptr1[:]
self.drinkList[resultIndex2].ing = ptr2[:]
def roulette(self):
sum = 0
lst = []
for x in self.drinkList:
sum += x.fitness
lst.append(sum)
return lst
def selectOne(self):
selection = random.randrange(self.pool[-1])
index = 0
while selection >= self.pool[index]:
index += 1
return index
def selectCouple(self):
selection1 = random.randrange(self.pool[-1])
index1, index2 = 0, 0
while selection1 >= self.pool[index1]:
index1 += 1
while True:
selection2 = random.randrange(self.pool[-1])
while selection2 >= self.pool[index2]:
index2 += 1
if not index1 == index2: break
return (index1, index2)
def save(self, text):
file.write(text)
for x in self.drinkList:
for y in x.ing:
file.write('min: ' + str(y.min) +
' max: ' + str(y.max) +
' value: ' + str(y.perc) + '\n')
file.write('\n\n')
file.write('\nPopulation fitness: ' +
str(self.calculatePopulationFitness()) +
'\n\n----------------------------------------------\n\n')
def run(self):
file.write("Genetic algorithm\n\nAttributes values:\n" +
"Mutation rate: " + str(mutationRate) +
"\nCrossover rate: " + str(crossoverRate) +
"\nIterations: " + str(iterations) +
"\nIngredients:\n\n" + str(ings))
self.save('\n\n--First population--\n\n')
for cnt in range(iterations):
self.updateFitness()
self.pool = self.roulette()
if random.random() < mutationRate:
index = self.selectOne()
self.showFitness('Mutation in iteration ' + str(cnt))
self.mutate(index)
self.updateFitness()
self.showFitness('Results: ')
if random.random() < crossoverRate:
index1, index2 = self.selectCouple()
self.showFitness('Crossover in iteration ' + str(cnt))
self.crossover(index1, index2)
self.updateFitness()
self.showFitness('Results: ')
self.save('--Final population--\n\n')
def calculatePopulationFitness(self):
sum = 0
for x in self.drinkList:
sum += x.fitness
return sum
def updateFitness(self):
for x in self.drinkList:
x.fitness = x.evaluate()
def showFitness(self, text):
lst = [x.fitness for x in self.drinkList]
all = sum(lst)
file.write(text + '\n' + str(lst) + '||' + str(all) + '\n')
To run it I create an instance of GeneticAlgorithm and launch it through run() method.
The problem is, for low level of iterations the program works more or less fine, but if I set iteration to 50 for example, it seems to fall in infinite loop or suspend at random iteration (the logfile is not updated anymore and the program does not stop - happenes at random iteration). What can be the cause of this?
PS: Can you suggest any changes to the coding style? I'm quite new to python and i don't know all the conventions yet.
I don't completely understand your algorithm but it looks like your code hangs in this loop here:
while True:
selection2 = random.randrange(self.pool[-1])
while selection2 >= self.pool[index2]:
index2 += 1
if not index1 == index2: break
It gets to a point where you never get a value where index1 != index2. This could either indicate you have a mistake somewhere in your code, or that there isn't a situation that meets this condition. You could try putting a cap on the number of iterations of this, for example:
iters = 0
while iters < 5000:
selection2 = random.randrange(self.pool[-1])
while selection2 >= self.pool[index2]:
index2 += 1
iters += 1
if index1 != index2: break
if iters == 5000:
# Deal with not being able to identify a Couple
I know the question is more than a year old. Still I wanted a GA code in python to start with and found the problem.
while True:
selection2 = random.randrange(self.pool[-1])
while selection2 >= self.pool[index2]:
index2 += 1
if not index1 == index2: break
The problem is in this loop. once index2 is found to be equal it is not reset back to zero before trying to find a new value.
while True:
index2 = 0
selection2 = random.randrange(self.pool[-1])
while selection2 >= self.pool[index2]:
index2 += 1
if not index1 == index2: break
After completely failing the minimax implementation for tic tac toe, I fail to see what's wrong. Right now, my AI just goes around in a circle...
import collections
class InvalidLocationError(Exception): pass
import copy
class Board(object):
def __init__(self, board=None):
if board is None:
self.clear()
else:
self._board = board[:]
def place(self, i, row, column):
if not ((0 <= row <= 2) and (0 <= column <= 2)):
raise InvalidLocationError("Invalid Location.")
if self._board[row][column]:
raise InvalidLocationError("There's already a piece there")
self._board[row][column] = i
return self.checkVictory()
def check(self, row, column):
return self._board[row][column]
def checkVictory(self, board=None):
if board is None:
board = self._board
draw = True
for i in xrange(3):
r = self.rowcount(i)
c = self.colcount(i)
if i < 3:
d = self.diagcount(i)
else:
d = {0: 0, 1: 0, 2: 0}
for j in xrange(1, 3):
if d[j] == 3 or r[j] == 3 or c[j] == 3:
return j
if r[0] > 0 or c[0] > 0:
draw = False
if draw:
return -1
return 0
def rowcount(self, row):
return collections.Counter(self._board[row])
def colcount(self, col):
return collections.Counter([self._board[i][col] for i in xrange(3)])
def diagcount(self, left=True):
if left:
a = [self._board[0][0], self._board[1][1], self._board[2][2]]
else:
a = [self._board[0][2], self._board[1][1], self._board[2][0]]
return collections.Counter(a)
def clear(self):
self._board = ([0, 0, 0], [0, 0, 0], [0, 0, 0])
def __str__(self):
return "\n".join(map(lambda x: " ".join(map(lambda y : str(y), x)), self._board))
#staticmethod
def flipPiece(p):
return int(not (p - 1)) + 1
class AI(object):
class Node(object):
def __init__(self, board, nextMove):
self.board = board
self.nextMove = nextMove
self.paths = []
self.score = None
template = self.board._board[:]
for r, row in enumerate(template):
for c, val in enumerate(row):
if val == 0:
template[r][c] = nextMove
self.paths.append(copy.deepcopy(template))
template[r][c] = 0
def __init__(self, mypiece, depth=8):
self.mypiece = mypiece
self.enemypiece = Board.flipPiece(mypiece)
self.depth = depth
def decide(self, board):
startNode = self.Node(board, self.mypiece)
best = self.minimax(startNode, self.depth)
for node in startNode.paths:
if node.value == best:
break
found = False
for row in xrange(3):
for col in xrange(3):
if board.check(row, col) != node.board.check(row, col):
found = True
break
if found:
break
print row, col
return row, col
def minimax(self, node, depth):
victory = node.board.checkVictory()
if victory:
if victory == self.mypiece:
h = 1
elif victory == -1:
h = 0
else:
h = -1
node.value = h
return h
if depth <= 0:
# h = self.heuristic(node.board, node.nextMove) # This is to the heuristic, which uses nextMove to evalate.
node.value = 0
return 0
h = -1
flip = Board.flipPiece(node.nextMove)
for i, board in enumerate(node.paths):
node.paths[i] = self.Node(Board(board), flip) # This is to the Node, which takes the nextMove of itself (which translates to the next next move from the current node)
score = self.minimax(node.paths[i], depth-1)
h = max(h, score) if node.nextMove == self.mypiece else min(h, score)
node.value = h
return h
Why is this happening?