我为8个拼图拼图写了一个解算器,以测试我对回溯和分支定界技术的理解。虽然它适用于一小部分配置,但它完全不适用于其他配置。
例如,它解决了以下配置:
[[],1,2],
[5,6,3],
[4,7,8]
但不是这一个:
[[],6,2],
[5,1,3],
[4,7,8]
我无法确定原因。我会感谢任何会审查我的代码的人。
from copy import deepcopy
class EightTile:
def __init__(self, initial_state):
self.state = initial_state
self.size = len(initial_state)
self.solvedState=[]
self.emptyPosition= self.findEmptyPosition(initial_state)
self.positionsDictionary={} # To facilitate position calculations
#Initialize solvedState & positionsDictionary
for i in range(self.size):
temp_rows=[]
for j in range(self.size):
if initial_state[i][j] ==[]:
self.emptyPosition = (i, j)
if i==2 and j==2:
temp_rows.append([])
else:
temp_rows.append(i+j+1+2*len(self.solvedState))
self.positionsDictionary[i+j+1+2*len(self.solvedState)] =(i,j)
self.solvedState.append(temp_rows)
def findEmptyPosition(self, state):
for i in range(self.size):
for j in range(self.size):
if state[i][j] ==[]:
return (i,j)
def calculateDistance(self,state): # Manhattan distance
distance=0
for i in range(self.size):
for j in range(self.size):
element = state[i][j]
if element!=[]:
right_position = self.positionsDictionary[element]
distance+= abs(right_position[0]-i) + abs(right_position[1]-j)
return distance
def generateLegalMoves(self, empty_position ):
moves=[]
if empty_position[0] +1 < self.size:
moves.append((empty_position[0]+1, empty_position[1]))
if empty_position[0] -1 >= 0:
moves.append((empty_position[0]-1, empty_position[1]))
if empty_position[1] +1 < self.size:
moves.append((empty_position[0], empty_position[1]+1))
if empty_position[1] -1 >= 0:
moves.append((empty_position[0], empty_position[1]-1))
return moves
def generateNextState(self, state):
boards=[]
emptyPosition= self.findEmptyPosition(state)
moves= self.generateLegalMoves(emptyPosition)
for move in moves:
currentBoard = deepcopy(state)
currentBoard[emptyPosition[0]][emptyPosition[1]], currentBoard[move[0]][move[1]] = \
currentBoard[move[0]][move[1]], currentBoard[emptyPosition[0]][emptyPosition[1]]
distance = self.calculateDistance(currentBoard)
boards.append((currentBoard, distance))
boards.sort(key=lambda x:x[1])
return [board[0] for board in boards] # Boards ordered by distance
def solve(self):
path=[self.state]
currentDistance= self.calculateDistance(self.state)
def solver(state, distance, path):
currentDistance = self.calculateDistance(state)
if state == self.solvedState:
return True
elif currentDistance > distance:
return False
else:
nextStates = self.generateNextState(state)
for s in nextStates:
path.append(s)
done= solver(s, currentDistance, path)
if done:
return True
else:
path.pop()
return False
def printSolution(path):
for board in path:
for row in board:
print(row)
print("")
solver(self.state, currentDistance, path)
printSolution(path)
board=\
[[[], 1, 2],
[5,6, 3],
[4, 7, 8]]
newboard= EightTile(board)
newboard.solve()