我正致力于建立一个完美的迷宫项目。 我有一个类Maze和一个Cell类代表迷宫中的每个方块。在我的Cell类中,我有四个布尔变量(北,南,东,西)来表示在单元格的北边或南边是否有墙。还有一个名为visit的布尔变量,用于检查是否已访问过该单元。这是我的Cell类 init ()的代码。
def __init__(self):
self.north = True
self.south = True
self.east = True
self.west = True
self.visit = False
对于Maze课程,我有self.maze(一堆Cell)和self.size = N(构建一个N * N迷宫)。 以下是Maze类的 init ():
def __init__(self, N):
self.size = N
self.maze = [[i for i in range(N + 2)] for i in range(N + 2)]
for r in range(self.size + 2):
for c in range(self.size + 2):
self.maze[r][c] = Cell()
当我更新迷宫索引时,我写了两个函数来检查newX和newY是否在1< = x< = self.size和1< = y< 1的范围内。 = self.size,以及是否已访问过该单元格。 这是代码:
def in_range(self, x, y):
if 1 <= x <= self.size and 1 <= y <= self.size:
return True
else:
return False
def is_valid(self, x, y):
if not self.maze[x][y].getVisit() and self.in_range(x,y):
return True
else:
return False
毕竟,我写了主要结构:
def walk(self, s, x, y):
neighbor = [(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)]
if s.size() == self.size**2: return
else:
while True:
new = choice(neighbor)#choice() is import from random
#print(self.is_valid(new[0], new[1]))
if self.is_valid(new[0], new[1]):break
else:
if len(neighbor) != 0:
neighbor.remove(new)
new = choice(neighbor)
else:
temp = s.pop(s)
self.walk(s, temp[0], temp[1])
break
print(new)
但是,运行我的代码仍会给我一个不在1和self.size之间的索引。我无法弄清楚为什么,我认为我的检查算法运行正常。 这是我得到的:
>>> ================================ RESTART
================================
>>>
>>> a = Maze(5)
>>> a.search()
1 2
(1, 3)
(2, 3)
(2, 4)
(1, 4)
(2, 4)
(2, 5)
(3, 5)
(4, 5)
(4, 4)
(4, 3)
(3, 3)
(3, 2)
(2, 2)
(2, 1)
(1, 1)
(0, 1)
(-1, 1)
(0, 1)
(1, 1)
(0, 1)
(-1, 1)
(-1, 2)
(-1, 1)
(0, 1)
有人可以帮帮我吗? PLZ,真的很感激!
答案 0 :(得分:0)
在Python range
中,如果您没有指定另一个起始位置,则从0开始。因此,当您初始化迷宫时,您有(0, *)
和(*, 0)
中的单元格:
for r in range(self.size + 2):
for c in range(self.size + 2):
self.maze[r][c] = Cell()
当你计算邻居时,你不能检查你是否已经离开:
neighbor = [(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)]
只有在将new
分配给这样的坐标后才能检查它是否有效。但是,如果它不有效并且没有邻居,则您再次呼叫walk
。您应该尝试独立于in_range
检查visit
。
此外,您的循环只能运行一次,因为new
有效并且您已经退出循环或者它无效并且您已经退出循环。
最后,您忘了向我们提供search
函数以及s
是什么(而s.pop(s)
看起来很有趣,因为pop
的参数通常是索引,而不是顺序)。
答案 1 :(得分:0)
您可以通过仔细查看walk()
或使用print
语句对其进行分析来找到这一点。
在网格的末端出现问题(当x或y == 0或N-1时)。除非您允许环绕,否则我假设您的网格初始化会在网格的北部(y == 0),南部,东部和西部放置墙。
顺便说一下,你的网格有两个不必要的行和列:如果你想要N个单元格,编号为O ..(N-1),那么使用range(N)
,而不是range(N+2)
,否则使用{{1 }}。 (你是否用有效的== False填充任何不需要的单元格?)
无论如何,range(1,N+1)
首先选择一个随机相邻小区,如果它是一个有效的小区,则会跳出while循环。但如果它不是,它会愉快地选择任何剩余的相邻小区(无论是否有效)和士兵。这是你的错误。始终测试有效性。
如果它已经用完了有效的邻居单元,它会通过执行walk()
来回溯。 s.pop(s)
也看起来像个bug。为什么不s.pop(s)
?
顺便说一下,调用变量s.pop()
而不是path
。
另外,这只是检查坐标的有效性;你从来没有真正检查过你是否曾经访问过这个单元格,所以你的递归回溯没有结束条件;你可以很容易地进入循环。
如果你重构s
使用一个单独的生成器walk()
,它会将已经测试过的随机选择的邻居返回为有效(和get_random_valid_neighbor()
当你用完邻居时,你可以帮助自己很多)。
None