代码审查:8个具有回溯功能的磁贴解算器无法解决大多数配置问题

时间:2017-01-22 02:28:38

标签: python algorithm puzzle backtracking

我为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()

0 个答案:

没有答案