我在python中遇到了一个奇怪的问题。我有一个迷宫,x代表墙壁,g是目标,s是起点,数字是门户网站,它们将你从一个号码带到另一个号码(例如,如果你继续使用其中一个号码,它将把你带到其他2)。
xxxxxxxxxxxxxxxxxxxx
x2 x
x xxx x
x 1 x xxxxx x
x s x x
x x x xxxxxxx
x xx xxxxx x
x x g x
x 1 x 2 x
xxxxxxxxxxxxxxxxxxxx
我正在尝试查找所有门户并将它们放入数组中。到目前为止,该程序可以找到所有四个门户网站。
import tkinter as tk
from tkinter import filedialog
root = tk.Tk()
root.withdraw()
file = filedialog.askopenfilename()
def readMazeToArray(path):
with open(path) as f:
return [list(line.strip()) for line in f]
maze = readMazeToArray(file)
def findPortals(maze):
portals = []
for i in range(0, len(maze)):
for j in range(0, len(maze[i])):
if (maze[i][j] != 'g' and maze[i][j] != 's'
and maze[i][j] != 'x' and maze[i][j] != ' '):
portals.append([i, j])
return portals
从那以后,事情变得有点奇怪。这里的代码似乎不正常:
def portalHeuristic(maze, x1, x2, y1, y2):
portals = findPortals(maze)
for portal in portals:
for i in range(0, len(maze)):
for j in range(0, len(maze[i])):
if maze[i][j] == maze[portal[0]][portal[1]]
and (portal[0] != i or portal[1] != j):
return abs(x1 - portal[0]) + abs(y1 - portal[1])
+ abs(x2 - i) + abs(y2 - j))
print(maze[i][j] == maze[portal[0]][portal[1]])
print("x1 = ", x1, ", y1 = ", y1, ", portal0 = ",
portal[0], ", portal1 = ", portal[1], ", x2 = ",
x2, ", y2 = ", y2, ", i = ", i, ", j = ", j)
portalHeuristic(maze, 4, 4, 7, 14)
portalHeuristic
基本上做的是它现在遍历一个门户网站,一个接一个地寻找当前门户网站的相同符号(maze[i][j] == maze[portal[0]][portal[1]]
),但确保它通过比较找不到当前门户网站当前门户网站的坐标及其找到的具有相同符号/编号(portal[0] != i or portal[1] != j
)的门户网站。最终它计算出发点和当前门户及其双门户和目标之间的距离。
但似乎maze[i][j] == maze[portal[0]][portal[1]]
似乎没有用,因为我的程序总是告诉我其他门户网站是在i = 9,j = 19找到的,无论哪个门户网站。奇怪的是,如果我在自己的python上测试字符串的相等性,就会意识到它总是错误的。我究竟做错了什么?我现在花了3个多小时寻找错误,但我似乎无法找到它。也许这是一个非常愚蠢的人?
另外,请忍受我可怕的代码。我刚开始使用python。
答案 0 :(得分:0)
在findPortal
方法中,您创建一个包含门户网站坐标的列表。最后它应该是这样的(它是随机数):portals = [[2,5], [5,1], ...]
在portalHeuristic
,条件为maze[i][j] == maze[portal[0]][portal[1]]
,portal[0] = [2,5]
和portal[1] = [5,1]
。所以基本上,你正在做maze[i][j] == maze[[2,5]][[5,1]]
,奇怪的是python没有引发异常。所以这就是为什么你的情况总是错误的。
如上所述,您的代码效率非常低。你在迷宫上迭代找到门户,然后在迷宫上再次重复(4次,因为你有4个门户)。在搜索门户时直接配对门户怎么样?你可以使用一个字典,其中的密钥是你的门户网站的编号(这里是1或2),它甚至可以是字符“1”或“2”而不是数字,而值将是一个包含2个元素的列表,每个元素都是门户网站的坐标。
def findPortals(maze):
portals = {} #That's a dict
for i in range(0, len(maze)):
for j in range(0, len(maze[i])):
if (maze[i][j] != 'g' and maze[i][j] != 's'
and maze[i][j] != 'x' and maze[i][j] != ' '):
if maze[i][j] in portals:
# We already have one, put the other
portals[maze[i][j]].append([i,j])
else:
# It is the first one
portals[maze[i][j]] = [[i,j]]
return portals
祝你好运!
你可以看到字典作为一个列表,其中键不需要是一个数字而不必是顺序的(如果列表中有5个项目,它们可以通过列表[0],列表[1]访问]等等。)。 因此,如果您想访问词典中的项目,只需传递密钥即可。在您的启发式中,您似乎想要找到[x1,y1]与列表中发现的第一个门户之间的距离,并将其与门户关联的[x2,y2]之间的其他距离相加。这有点过于具体,您可以指定要检查的门户(例如“1”或“2”)。
因此,您的功能变为:
def portalHeuristic(portals, x1, y1, x2, y2, portal_number):
# Check if the portal exist in you list
if portal_number not in portals:
print("This portal number is not in the list")
return
# This line is a shortcut. Since we know that portals[x] is a list of
# two elements (coordinates of both portals with the same number),
# you can assign the first element with first_portal and the second element
# with second_portal.
first_portal, second_portal = portals[portal_number]
return abs(x1 - first_portal[0]) + abs(y1 - first_portal[1])
+ abs(x2 - second_portal[0]) + abs(y2 - second_portal[1]))
不要忘记你的密钥是那里的字符('1'或'2')而不是1或2(整数)。 portal_number
应该是一个角色。
答案 1 :(得分:0)
一旦你熟悉列表推导就很难写出for
循环
但是也许你可以从我的示例列表comps http://treyhunner.com/2015/12/python-list-comprehensions-now-in-color/
向后工作我在listcomps中添加了换行符和前导空格,以帮助提高可读性
您还应该看到enumerate
在这些类型的索引循环中非常有用,并且对元素进行了测试
maze = ['xxxxxxxxxxxxxxxxxxxx',
'x2 x',
'x xxx x',
'x 1 x xxxxx x',
'x s x x',
'x x x xxxxxxx',
'x xx xxxxx x',
'x x g x',
'x 1 x 2 x',
'xxxxxxxxxxxxxxxxxxxx']
prtls = [[c, (j, k)]
for k, ln in enumerate(maze)
for j, c in enumerate(ln) if c.isdigit()]
prtls
Out[206]: [['2', (1, 1)], ['1', (4, 3)], ['1', (4, 8)], ['2', (10, 8)]]
grpd_prtls = [[n, [p[1]
for p in prtls if p[0] == n]]
for n in sorted(set(p[0] for p in prtls))]
grpd_prtls
Out[207]: [['1', [(4, 3), (4, 8)]], ['2', [(1, 1), (10, 8)]]]
grpd_prtls
按门户网站号sorted(set(p[0] for p in prtls))
从我的grpd_prtls计算'Manhatten Distance',每个数字只需2个门户
[[p[0], sum(abs(a-b)
for a, b in zip(*p[1]))]
for p in grpd_prtls]
Out[214]: [['1', 5], ['2', 16]]