使用递归的python迷宫

时间:2016-02-05 03:44:16

标签: python recursion backtracking maze

我想用递归来解决迷宫问题。该程序打开一个文本文件,如下所示:

10 20
1 1 
10 20
-----------------------------------------
|     |     | |     | | |       |     | |
|-+ +-+-+ +-+ + +-+ + + +-+-+ +-+-+ + + |
|         |       |     | | | |   | |   |
| + +-+ + + +-+-+-+ + + + + + +-+ + + + |
| | |   |     |     | |     |       | | |
| +-+-+-+-+ +-+ +-+-+-+-+ +-+ + +-+-+ +-|
| | | |       |   | |         | |   |   |
| + + +-+ +-+-+ + + + +-+ +-+ + + + +-+ |
|     |     |   | |     | |   |   | | | |
|-+-+ +-+-+-+-+-+-+-+ +-+ +-+-+ +-+-+ +-|
| |   |   |     |     |     |   | | | | |
| +-+-+ +-+-+ +-+ + +-+-+ +-+ +-+ + + + |
|       |     | | |   |   | | | |       |
|-+ +-+ + + +-+ +-+-+ + +-+ + + +-+ +-+ |
|   | | | |     | | | | | | | |   | | | |
|-+ + +-+ + + + + + +-+ + + + + +-+-+ + |
|       | | | |     |     |             |
| + + +-+ + +-+-+-+ + +-+ + + +-+-+ +-+ |
| | |     | |           | | | |     |   |
-----------------------------------------

文件的第一行是迷宫的大小(10 20),第二行是起点(1 1),第三行是出口(10,20)。我想用" *"标记正确的路径。这就是我的代码:

编辑:我更改了findpath()功能中的一些代码,现在我没有收到任何错误,但迷宫是空的,路径(' *')不是&# 39;绘制'在迷宫上。

class maze():    
    def __init__(self, file):

        self.maze_list = []

        data= file.readlines()

        size = data.pop(0).split()  # size of maze

        start = data.pop(0).split() # starting row and column; keeps being 0 because the previous not there anymore
        self.start_i = start[0]  # starting row
        self.start_j = start[1]  # starting column

        exit = data.pop(0).split()   # exit row and column 
        self.end_i = exit[0]
        self.end_j = exit[1]

        for i in data:  
            self.maze_list.append(list(i[:-1])) # removes \n character off of each list of list
        print(self.maze_list) # debug


    def print_maze(self):

        for i in range(len(self.maze_list)):
            for j in range(len(self.maze_list[0])):  
                print(self.maze_list[i][j], end='')                         
            print()

def main():

    filename = input('Please enter a file name to be processed: ') # prompt user for a file


    try:
        file = open(filename, 'r')
    except:                     # if a non-existing file is atempted to open, returns error 
        print("File Does Not Exist")
        return  

    mazeObject = maze(file)
    mazeObject.print_maze() # prints maze

    row = int(mazeObject.start_i)
    col = int(mazeObject.start_j)   

    findpath(row, col, mazeObject)  # finds solution route of maze if any

def findpath(row, col, mazeObject):

    if row == mazeObject.end_i and col == mazeObject.end_j: # returns True if it has found the Exit of the maze
        mazeObject.maze_list[row][col] = ' ' # to delete wrong path
        return True

    elif mazeObject.maze_list[row][col] == "|": # returns False if it finds wall 
        return False

    elif mazeObject.maze_list[row][col] '-': # returns False if it finds a wall 
    return False

    elif mazeObject.maze_list[row][col] '+': # returns False if it finds a wall 
        return False    

    elif mazeObject.maze_list[row][col] '*': # returns False if the path has been visited
        return False

    mazeObject.maze_list[row][col] = '*'   # marks the path followed with an *   

    if ((findpath(row + 1, col, mazeObject)) 
        or (findpath(row, col - 1, mazeObject)) 
        or (findpath(row - 1, col, mazeObject)) 
        or (findpath(row, col + 1, mazeObject))):    # recursion method
        mazeObject.maze_list[row][col] = ' '  # to delete wrong path
        return True
    return False    

所以现在我的问题是,错误在哪里?我的意思是程序只是在没有解决方案的情况下打印出迷宫。我想用" *"填充正确的路径。

1 个答案:

答案 0 :(得分:2)

查看代码,我看到了几个错误。您没有正确处理进入和退出行/列对。 (10,20)对于这个迷宫是正确的,如果你假设每隔一行和每隔一列都是一个网格线。也就是说,如果|-字符代表无限细线,偶尔会出现断裂,就像传统的迷宫图纸一样。

您需要多次/除以2,并处理不可避免的fencepost错误,以便将文件参数正确转换为数组行/列值。

接下来,您的findpath功能很混乱:

首先,它应该是班级的一种方法。它访问内部数据,并包含内部知识"关于班级细节。把它变成一种方法!

其次,退出条件用空格替换当前字符"删除错误的路径"。但是如果你找到了出口,那么路径是正确的。别这么做!

第三,你有各种各样的字符类型的if语句。这很好,但请使用

用一个if语句替换它们
if self.maze_list[row][col] in '|-+*':
    return False

第四,你等着用' *'标记当前单元格。直到你的检查。但是当你到达出口位置宣布胜利之前,你应该标记单元格。我认为,将退出测试向下移动。

这应该很好地清理。

第五,最后,你的递归测试是倒退的。当您的代码到达退出位置时,它会返回True。当代码遇到问题时,您的代码会返回False,或者尝试跨越自己的路径。因此,如果代码采用死路径,它将到达结尾,返回false,将递归展开几次,一直返回false,直到它返回。

因此,如果您看到True返回,您就知道代码在该路径下找到了退出。您希望立即返回true并执行其他。当然不要擦除路径 - 它会通向出口!

另一方面,如果你的任何一个方向都没有返回,那么你就找到了一个死胡同 - 出口不在这个方向。您应该删除路径,返回False,并希望可以在更高级别找到退出。