Maze path finding is an interesting problem to find if there path(and the path) between start and dest points on grid. More details on wiki. There many solutions some of them are more complicate than others. I am looking at backtracking or A* search. Normally simple solution is model the grid (open cells) as graph nodes and try to find shorted path between two nodes.

In this instance of this problem, there is an extra requirement. At each cell, you can only move into one of neighbours cells (left, right, up and down). so, recursion looks like a good solution here.

Starting from Point(or cell) class with some utility methods.

class Point:
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    def randomize(self,N):
        self.x = random.randrange(0, N)
        self.y = random.randrange(0, N)

    def __iter__(self):
        yield self.x
        yield self.y

    def __str__(self):
            return "({0},{1})".format(self.x,self.y)

    def __eq__(self, other):
        if (self.x == other.x and self.y == other.y):
            return True
        else:
            return False

Another utility methos is get_adj which calculates the agj neighbours of given cell

        def get_adj(point):
            adj = []
            for idx in [-1, 1]:
                if (point.x + idx < self.N and point.x + idx >=0 ):
                    p = Point(point.x + idx, point.y)
                    adj.append(p)

                if (point.y + idx < self.N and point.y +idx >=0 ):
                    p = Point(point.x , point.y + idx)
                    adj.append(p)
            return adj

Finally, The recursive function move iterates over open neighbours cells. The recursion breaks if dest is found or neighbours are iterated. Well, Something i had to do is limit recursion to neighbours except the one i already come from otherwise, it can get stuck between two points.

    def run(self):


        def move(point, prev, dest):

            print(f"move called with {point}")
            if point == dest:
                return True

            adj = get_adj(point)

            for p in adj:
                if self.grid[tuple(p)] and (not (p==prev)):
                    res =  move(p, point, dest)
                    print(f"Results:{res} point:{point} adj:{p} prev:{prev}")
                    if res:
                        return True

            return False

Finally, this is not really path between start and dest. move can return True if there is a path between and start and dest. that said, the recursion can print the path while unrolling the recursive call. Maybe in another evening!