Я нашел этот код, чтобы решить лабиринт, как это:

+-+-+-+-+-+-+-+-+-+-+
| |         |   |   |
S +-+-+-+-+ + +-+ + +
|         | |     | |
+-+-+-+ +-+ +-+-+-+ +
|     | |   |       |
+ + + + + +-+ +-+-+-+
| | | | |       |   |
+ + +-+ +-+-+ + + + +
| |   | |   | |   | |
+ +-+ + + + + +-+-+-+
| |   |   | |       |
+ + +-+-+-+ + +-+-+ +
| |         | |     |
+ +-+-+ +-+-+ +-+-+-+
| |   |     |   |   |
+ + + +-+-+-+-+ + +-+
| | | | |       |   |
+ + + + + + +-+-+-+ +
|   |     |         E
+-+-+-+-+-+-+-+-+-+-+

Это код:

def read_maze(fname):
    mz = []
    with open(fname, 'U') as f:
        for r in f:
            mz.append(list(r.replace('\n', '')))
    return mz



PATH, START, EXIT, VISITED, SOLUTION = " SE.o"


class Maze():
    def __init__(self,maze):
        self.maze = maze
        self.start_y = [row.count(START) for row in self.maze].index(1)
        self.start_x = self.maze[self.start_y].index(START)
    def __repr__(self):
        return  "\n".join("".join(row)for row in self.maze)
    def solve(self, x=None, y=None):
        if x==None:
            x, y = self.start_x,self.start_y
        if self.maze[y][x] in (PATH,START):
            self.maze[y][x] = VISITED
            if self.solve(x+1,y) or self.solve(x-1,y) or self.solve(x,y+1) or self.solve(x,y-1):
                self.maze[y][x]=SOLUTION
                return True
        elif self.maze[y][x] == EXIT:
            return True
        return False

maze = read_maze("maze.txt")


mz = Maze(maze)
print (mz)
print ("-----------------------------")
if mz.solve():
    print(mz)

Может ли кто-нибудь помочь мне понять рекурсивную функцию solve()?

Прежде всего, функция проверяет, находится ли текущая позиция в PATH или START, она, очевидно, будет в START впервые, что в нашем случае равно (x = 0; y = 2). Таким образом, код пометить его как VISITED.

Что я не совсем понимаю, что программа делает дальше? Существует условие if, и первая опция для проверки - self.solve(x+1,y) - в этом случае мы идем направо, это свободная позиция и она находится в PATH (поэтому мы помечаем ее как VISITED), но (x + 1 + 1, y) нет, поэтому мы переходим ко второму значению нашего or (то есть (x-1,y), поэтому получаем снова (x+1+(1-1),y) = (x+1,y), теперь мы переходим к третьему {{X4 }} так что мы идем вниз и т. д.

Это правильно? Я немного потерян.

-4
Lime In The Coconut 27 Май 2017 в 19:52

2 ответа

Лучший ответ

Встроенное объяснение

def solve(self, x=None, y=None):

    # initializes x, y as start location
    # occurs during first call of 'solve', i.e. zeroth recursion
    if x==None: 
        x, y = self.start_x,self.start_y

    # equivalent to, if the current (x, y) tile is walk-able
    # implicitly ignores visited tiles
    if self.maze[y][x] in (PATH,START):

        # mark tile (x, y) as visited
        self.maze[y][x] = VISITED

        # if one of the adjacent tiles from (x, y) leads to a solution
        # this is where the recursion occurs, i.e. 'solve' is called using the adjacent tiles
        # this will be recursively called until one of the calls return True upon finding the exit
        # when one of the calls encounter an exit, then this will create a chain reaction where each call returns True to its caller until the first call returns true
        if self.solve(x+1,y) or self.solve(x-1,y) or self.solve(x,y+1) or self.solve(x,y-1):

            # mark (x, y) as part of the solution
            self.maze[y][x]=SOLUTION

            # tells that a solution has been found, value used by caller
            return True

    # if the (x, y) tile is the exit then a solution has been found
    elif self.maze[y][x] == EXIT:
        return True

    # if non of the if statements return, then by default no solution has been found where tile (x, y) is in the solution path.
    return False

Легенды лабиринта

  • <space> плитка
  • S стартовая плитка
  • E выходная плитка
  • . посещенная плитка
  • o плитка, которая является частью пути решения
  • все остальные плитки не пригодны для ходьбы

Лабиринт перед solve()

+-+-+-+-+-+-+-+-+-+-+
| |         |   |   |
S +-+-+-+-+ + +-+ + +
|         | |     | |
+-+-+-+ +-+ +-+-+-+ +
|     | |   |       |
+ + + + + +-+ +-+-+-+
| | | | |       |   |
+ + +-+ +-+-+ + + + +
| |   | |   | |   | |
+ +-+ + + + + +-+-+-+
| |   |   | |       |
+ + +-+-+-+ + +-+-+ +
| |         | |     |
+ +-+-+ +-+-+ +-+-+-+
| |   |     |   |   |
+ + + +-+-+-+-+ + +-+
| | | | |       |   |
+ + + + + + +-+-+-+ +
|   |     |         E
+-+-+-+-+-+-+-+-+-+-+

Лабиринт после solve()

+-+-+-+-+-+-+-+-+-+-+
| |.........|...|...|
oo+-+-+-+-+.+.+-+.+.+
|ooooooo..|.|.....|.|
+-+-+-+o+-+.+-+-+-+.+
|ooo..|o|...|.......|
+o+o+.+o+.+-+.+-+-+-+
|o|o|.|o|.......|...|
+o+o+-+o+-+-+.+.+.+.+
|o|ooo|o|ooo|.|...|.|
+o+-+o+o+o+o+.+-+-+-+
|o|ooo|ooo|o|.......|
+o+o+-+-+-+o+.+-+-+.+
|o|ooooooooo|.|.....|
+o+-+-+ +-+-+.+-+-+-+
|o|ooo|     |...|   |
+o+o+o+-+-+-+-+.+ +-+
|o|o|o| |ooo....|   |
+o+o+o+ +o+o+-+-+-+ +
|ooo|ooooo|oooooooooE
+-+-+-+-+-+-+-+-+-+-+
2
EyuelDK 27 Май 2017 в 17:41

solve возвращает True только в том случае, если код находится на плитке выхода или на части пути, ведущего к плитке выхода. Теперь код рекурсивно погружается в лабиринт: каждый раз, когда найден тайл 'PATH', он помечает его как VISITED и посещает все соседние тайлы (следующая рекурсия) или настенный тайл, на котором он возвращает 'False' (может не продолжать это направление). Это продолжается до тех пор, пока не будет найден тайл EXIT, который возвращает первый «True». Это уменьшает рекурсию на единицу и изменяет флаг VISITED на SOLUTION, снова возвращает True, снова уменьшая рекурсию. Теперь это продолжается до тех пор, пока код не вернется на плитку START.

Надеюсь это поможет.

1
Thomas Kühn 27 Май 2017 в 17:25