PythonBFS程序不返回网格和路径,在迷宫上有障碍物和解决方案

PythonBFS程序不返回网格和路径,在迷宫上有障碍物和解决方案,python,algorithm,data-structures,breadth-first-search,maze,Python,Algorithm,Data Structures,Breadth First Search,Maze,我导入了一个带有数字的文本文件,如下例所示: 0 0 0 0 0 1 0 0 3 0 3 0 0 0 3 0 0 0 0 3 0 3 0 0 0 0 3 3 0 3 0 0 0 0 0 0 0 3 3 0 3 0 0 0 0 0 0 0 2 3 3 3 0 3 0 0 0 0 0 0 0 0 0 3 3 3 3 0 3 0 0 0 0 0 0 0 0 3 3 3 3 3 3 3 目标是读取文本文件,将其格式化为一个我能够做到的网格(即10×10的网格),然后对列表列表进行排序,以获得解决方案

我导入了一个带有数字的文本文件,如下例所示:


0 0 0 0 0 1 0 0 3 0 3 0 0 0 3 0 0 0 0 3 0 3 0 0 0 0 3 3 0 3 0 0 0 0 0 0 0 3 3 0 3 0 0 0 0 0 0 0 2 3 3 3 0 3 0 0 0 0 0 0 0 0 0 3 3 3 3 0 3 0 0 0 0 0 0 0 0 3 3 3 3 3 3 3


目标是读取文本文件,将其格式化为一个我能够做到的网格(即10×10的网格),然后对列表列表进行排序,以获得解决方案,其中数字3是障碍,数字1是起点,数字2是解决方案,我尝试使用BFS算法,代理可以上下左右移动

我试图打印从起点(即1)到最接近的解决方案(即2)所采取的步骤序列。数字的格式为字符串/文本。我编写的程序似乎正在运行,但它从未打印解决方案或终止。要打印为解决方案的移动序列的格式为:


“下移” “向上移动” 等等,每一步都在一条换行线上

我在下面附上我的代码,如能提供任何帮助,将不胜感激

    import queue


def read_user_input():
    file_name = input('Enter the name of your file :\n')
    return file_name


def read_to_grid():
    file_name = read_user_input()
    for nums in open(file_name):
        line = list(nums.split())
        result = []
        for _ in range(0, len(line), 10):
            result.append(line[_:_ + 10])
        return result
    file_name.close()


def print_grid(result, path=''):
    for x, pos in enumerate(result[0]):
        if pos == '0':
            start = x

    i = start
    j = 0
    pos = set()
    for move in path:
        if move == 'Move Left':
            i -= 1
        elif move == 'Move Right':
            i += 1
        elif move == 'Move Up':
            j -= 1
        elif move == 'Move Down':
            j += 1

        pos.add((j, i))
    for j, row in enumerate(result):
        for i, col in enumerate(row):
            if (j, i) in pos:
                print('#', end='')
            else:
                print(col + ' ', end='')
        print()


def valid(result, moves):
    for x, pos in enumerate(result[0]):
        if pos == '0':
            start = x

    i = start
    j = 0
    for move in moves:
        if move == 'Move Left':
            i -= 1
        elif move == 'Move Right':
            i += 1
        elif move == 'Move Up':
            j -= 1
        elif move == 'Move Down':
            j += 1
        if not (0 <= i < len(result[0]) and 0 <= j < len(result)):
            return False
        elif (result[i][j] == '3'):
            return False

    return True


def find_goal(result, moves):
    for x, pos in enumerate(result[0]):
        if pos == '0':
            start = x

    i = start
    j = 0
    for move in moves:
        if move == 'Move Left':
            i -= 1
        elif move == 'Move Right':
            i += 1
        elif move == 'Move Up':
            j -= 1
        elif move == 'Move Down':
            j += 1

    if result[j][i] == '2':
        print('Found: ' + moves)
        print_grid(result, moves)
        return True

    return False


nums = queue.Queue()
nums.put('')
add = ''
result = read_to_grid()

while not find_goal(result, add):
    add = nums.get()
    for j in ['Move Left', 'Move Right', 'Move Up', 'Move Down']:
        put = add + j
        if valid(result, put):
            nums.put(put)
导入队列
def read_user_input():
file\u name=input('输入文件名:\n')
返回文件名
def read_to_grid():
文件名=读取用户输入()
对于打开的NUM(文件名):
line=list(nums.split())
结果=[]
对于范围内的(0,长度(线),10):
result.append(第[\u10]行)
返回结果
文件名。关闭()
def打印网格(结果,路径=“”):
对于x,枚举中的位置(结果[0]):
如果pos==“0”:
开始=x
i=开始
j=0
pos=set()
对于移入路径:
如果移动=='向左移动':
i-=1
elif move==“向右移动”:
i+=1
elif move==“上移”:
j-=1
elif move==“下移”:
j+=1
位置添加((j,i))
对于j,枚举中的行(结果):
对于i,枚举中的列(行):
如果(j,i)处于位置:
打印(“#”,结束=”)
其他:
打印(列+'',结束='')
打印()
def有效(结果、移动):
对于x,枚举中的位置(结果[0]):
如果pos==“0”:
开始=x
i=开始
j=0
对于移入移动:
如果移动=='向左移动':
i-=1
elif move==“向右移动”:
i+=1
elif move==“上移”:
j-=1
elif move==“下移”:
j+=1

如果不是(0在调试代码时,当涉及到“valid”和“find_goal”函数时,我遇到了一些无休止的循环和其他错误

根据我使用宽度优先搜索的经验,最好将每个点视为一个节点(本例中的坐标)让您的队列由当前正在尝试的路径列表组成。其中,每个路径都是被跨越的每个节点的列表。通常,您不希望在给定路径中多次访问同一节点,因此您必须跟踪此信息,而不是单独的“左”、“右”等

综上所述,我构建了您的代码并创建了一个函数,当给定一个节点(不是3)并考虑该节点是否已被访问时,该函数将返回有效的相邻节点。然后,对于BFS部分,队列以包含起始节点的列表开始(我创建了一个函数以查找1所在的位置)。然后,当队列存在时,BFS将弹出当前路径,获取该路径中的最后一个节点,找到所有有效的相邻节点。对于每个有效的相邻节点,新的路径条目将添加到由旧路径+相邻节点组成的队列中。如果其中一个相邻节点是目标,它将结束搜索并返回路径。我已包括在内路径中的方向信息,以便您可以将其解析出来

这应该打印出一条到最近的2的路径,例如:

[((5, 0), ''), ((5, 1), 'Down'), ((6, 1), 'Right'), ((6, 2), 'Down'), ((7, 2), 'Right'), ((7, 3), 'Down'), ((7, 4), 'Down'), ((7, 5), 'Down')]
您将看到
…排序(path\u queue,key=lambda…
该行不需要,但它是一种惰性的队列优先级排序方法,总是尝试最短的当前路径。如果删除它,您将看到仍然得到有效的路径,但路径要长得多

def read_user_input():
file\u name=input('输入文件名:\n')
返回文件名
def read_to_grid():
文件名=读取用户输入()
对于打开的NUM(文件名):
line=list(nums.split())
结果=[]
对于范围内的(0,长度(线),10):
result.append(第[\u10]行)
int_结果=[]
对于i,枚举中的行(结果):
int_result.append([])
对于行中的列:
int_结果[i]。追加(int(col))
返回整数结果
def打印网格(结果,路径=“”):
对于x,枚举中的位置(结果[0]):
如果pos==0:
开始=x
i=开始
j=0
pos=set()
对于移入路径:
如果移动=='向左移动':
i-=1
elif move==“向右移动”:
i+=1
elif move==“上移”:
j-=1
elif move==“下移”:
j+=1
位置添加((j,i))
对于j,枚举中的行(结果):
对于i,枚举中的列(行):
如果(j,i)处于位置:
打印(“#”,结束=”)
其他:
打印(str(col)+'',end='')
打印()
def find_start_节点(网格):
对于i,枚举(网格)中的行:
如果第1行为:
返回((行索引(1),i),“”)
返回(无,无)
def valid_adj(当前节点、网格、已访问):
x=当前节点[0][0]
y=当前节点[0][1]
adj=[]
如果((y+1)<10)和(网格[y+1][x]!=3)和非(任何((x,y+1)在节点中用于访问的节点)):
附加(((x,y+1),“向下”))
如果((x+1)<10)和(网格[y][x+1]!=3)和非(任何((x+1,y)在节点中用于访问的节点)):
附加(((x+1,y),‘右’))
如果((y-1)>=0)和
import queue

# Read name file from user
def read_user_input():
    file_name = input('Enter the name of your file :\n')
    return file_name

# Read file and return list of list[10]
def read_to_grid():
    with open(read_user_input()) as file:
        for nums in file:
            line = list(nums.split())
            return line

# Shows a text grid
def print_grid(result, path=[]):
    for x, pos in enumerate(result):
        if pos == '1':
            start = x

    i = start
    #j = 0
    pos = set()
    
    for move in path:
        if move == 'Move Left':
            i -= 1
        elif move == 'Move Right':
            i += 1
        elif move == 'Move Up':
            i -= 10
        elif move == 'Move Down':
            i += 10

        pos.add(i)

    for i, celd in enumerate(result):
        if i % 10 == 0:
            print()
        if i in pos:
            print('# ', end='')
        else:
            print(celd + ' ', end='')      

# Validates coordinates and traveled path
def valid(result, moves):
    for x, pos in enumerate(result):
        if pos == '1':
            start = x

    i = start % 10
    j = start // 10

    # Where we start
    travel = [(j,i)]

    for move in moves:
        if move == 'Move Left':
            i -= 1
        elif move == 'Move Right':
            i += 1
        elif move == 'Move Up':
            j -= 1
        elif move == 'Move Down':
            j += 1

        # Check if we have already been there
        if (j, i) in travel:
            return False
        else:
            travel += [(j,i)]

        # Check coordinates
        if i >= 10 or i < 0 or j >= len(result) // 10 or j < 0:
            return False
        elif result[i+j*10] == '3':
            return False

    return True

# Return true if 2 is reached
def find_goal(result, moves):
    for x, pos in enumerate(result):
        if pos == '1':
            start = x

    i = start
    #j = 0
    for move in moves:
        if move == 'Move Left':
            i -= 1
        elif move == 'Move Right':
            i += 1
        elif move == 'Move Up':
            i -= 10
        elif move == 'Move Down':
            i += 10

    if result[i] == '2':
        print('Found: ',' '.join(moves))
        print_grid(result, moves[0:-1])
        return True

    return False

nums = queue.Queue()
result = read_to_grid()
add = []

while not find_goal(result, add):
    if not nums.empty():
        add = nums.get()
    for j in ['Move Left', 'Move Right', 'Move Up', 'Move Down']:
        put = add + [j]
        if valid(result, put):
            nums.put(put)
import queue

# Read name file from user
def read_user_input():
    file_name = input('Enter the name of your file :\n')
    return file_name

# Read file and return list of list[10]
def read_to_grid():
    with open(read_user_input()) as file:
        for nums in file:
            line = list(nums.split())
            return line

# Shows a text grid
def print_grid(result, path=[]):
    pos = set()
    
    for (x,y), _ in path:
        i = x + y*10
        pos.add(i)

    for i, celd in enumerate(result):
        if i % 10 == 0:
            print()
        if i in pos:
            print('# ', end='')
        else:
            print(celd + ' ', end='')      

# Validates coordinates and traveled path
def valid(result, moves):
    # Unpack
    (i,j), _ = moves[-1]

    # Check if already traveled
    if any(x == i and y == j for (x,y), __ in moves[:-1]):
        return False

    # Check coordinates
    if i >= 10 or i < 0 or j >= len(result) // 10 or j < 0:
        return False
    elif result[i+j*10] == '3':
        return False

    return True

# Return true if 2 is reached
def find_goal(result, moves):
    # Unpack
    (i,j), _ = moves[-1]

    if result[i+j*10] == '2':        
        #Print moves
        output = 'Found: '
        for (x,y), _ in moves:
            output += " "+_
        print(output)       
        #Print grid
        print_grid(result, moves[1:-1])

        return True
        
    return False

# Return new position and which movement was done.
def move(pos, dir):
    (x, y), _ = pos
    
    if dir == 'Move Left':
        x -= 1
    elif dir == 'Move Right':
        x += 1
    elif dir == 'Move Up':
        y -= 1
    elif dir == 'Move Down':
        y += 1
    
    return (x, y), dir 

nums = queue.Queue()
result = read_to_grid()

# Find the starting position
for x, pos in enumerate(result):
    if pos == '1':
        start = x

add = [((start % 10, start // 10),'')]

while not find_goal(result, add):
    if not nums.empty():
        add = nums.get()
    for j in ['Move Left', 'Move Right', 'Move Up', 'Move Down']:
        put = add + [move(add[-1],j)]
        if valid(result, put):
            nums.put(put)