【问题标题】:check validation for input for perfect maze检查完美迷宫的输入验证
【发布时间】:2015-04-05 07:32:41
【问题描述】:

我正在做一个项目来建造一个完美的迷宫。 我有一个 Maze 类和一个 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

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)

有人可以帮帮我吗? lz,真的很感激!

【问题讨论】:

  • 又是build-a-perfect-maze一周吗?
  • 你为什么到处使用range(N + 2)?这将创建一个 (N+1)x(N+1) 迷宫。只需创建一个numpy.array 的 Cell。
  • 很高兴为您提供帮助。能否请您发布您的迷宫和牢房的课程代码?
  • if s.size() == self.size**2: return 在检查什么?那是怎样的终止条件?除非您尝试随机发现长度为 N**2 的路径(但它们不一定是循环或完全遍历)。
  • 因为教授说要建立一个 N+2 迷宫以避免一些乏味的问题。老实说,我也不知道原因。

标签: python recursion path-finding maze


【解决方案1】:

在 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。您应该尝试独立于visit 来检查in_range

此外,您的循环只能运行一次,因为 new 有效并且您跳出循环,或者它无效并且您跳出循环。

最后,你忘了给我们search 函数以及s 是什么(s.pop(s) 看起来很有趣,因为通常pop 的参数是一个索引,而不是序列)。

【讨论】:

    【解决方案2】:

    您可以通过仔细查看walk() 或使用print 语句对其进行跟踪来找到它。 网格的末端出现问题(当 x 或 y == 0 或 N-1 时)。除非您允许环绕,否则我假设您的网格初始化会将墙壁放在网格的北部(y==0)、南部、东部和西部。 顺便说一句,您的网格有两个不必要的行和列:如果您想要 N 个单元格,编号为 O..(N-1),则使用range(N),而不是range(N+2),或者使用range(1,N+1)。 (您是否使用 valid==False 填充任何不需要的单元格?)

    无论如何,walk() 首先选择一个随机相邻单元格,如果它是有效单元格,则退出 while 循环。但如果不是,它会高兴地选择任何剩余的相邻单元(无论是否有效)并继续使用士兵。那是你的错误。始终测试有效性。 如果它已经用完了有效的相邻小区,它会通过执行s.pop(s) 回溯。 s.pop(s) 也看起来像一个错误。为什么不s.pop()? 顺便说一句,调用变量path 而不是s

    另外,这只是检查坐标的有效性;你从来没有真正检查过你以前是否访问过那个单元格,所以你的递归回溯没有结束条件;你可以很容易地进入循环。

    如果您将 walk() 重构为使用单独的生成器 get_random_valid_neighbor(),它会返回已被测试为有效的随机选择的邻居(当您的邻居用完时返回 None),您可以帮助自己。

    def walk(self, s, x, y):
    
    ...
          while True:
                new = choice(neighbor)
                if self.is_valid(new[0], new[1]):break # tested for validity
                else:
                    if len(neighbor) != 0:
                        neighbor.remove(new)
                        new = choice(neighbor) # BUG: never tested for validity
                    ...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-10-14
      • 2019-11-03
      • 2020-09-26
      • 2015-06-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-12
      相关资源
      最近更新 更多