"困惑的挖掘机&#​​34;算法运行速度太慢,有什么方法可以加快速度?

时间:2017-02-10 23:14:07

标签: python algorithm maze roguelike

我有一个基于回溯迷宫算法的算法,删除了一些部分,从而形成了这个美妙的地牢。不幸的是,它运行非常慢这使得几乎不可能填充一个体面大小的地图。我真的不想把它扔出去,但我无法想出任何加速它的方法。我使用的是Python,所以我知道这是我的问题的一部分,但我并没有准备好抛弃我的roguelike现有的整个代码库,它现在运行得足够快。这是目前的代码:

    start = (random.randint(0, self.width), random.randint(0, self.height))
    self.dungeon['up_stairs'] = start

    visited = [start]
    while len(visited) < 300:
        current = visited[-1]
        apos = random.choice([(1, 0), (0, 1), (0, -1), (-1, 0)])
        new = utils.tuple_add(current, apos)
        if not new in visited and self.on_map(new):
            self.place_cell(new, is_wall=False)
            visited.append(new)
        else:
            visited.pop()

[编辑]

  1. 要回答评论中的一些问题,place_cell会根据位置参数is_wall在提供的位置元组处创建一个墙或一个空单元格。例如,在上面的代码中,self.place_cell(new, is_wall=False)调用会将地图上新位置的单元格更改为空单元格。
  2. 访问应该被称为其他东西,我只是......懒惰的那种方式。我可能会在以后修复它。
  3. < 300条件是因为299个单元格在合理的时间范围内可以绘制得最多。 (超过299个细胞,它突然开始悬挂。)

1 个答案:

答案 0 :(得分:2)

我建议进行以下改进:

  • 不要仅因为您在一步失败而弹出被访问的单元格。这可能导致饥饿:弹出并再次尝试,弹出......等等。您应该选择过去访问过的另一个单元格,并从那里继续。如果失败,请选择另一个......

  • 使用set跟踪已访问的单元格:这样可以更快地查找

  • 使用另一个&#34;边境&#34; set用于跟踪哪些访问过的单元格仍有未访问的邻居

  • 访问单元格时,以随机顺序检查所有邻居是否未访问。第一个将是您的下一次访问。但如果所有这些都被访问过(或在网格外),那么从边界集中选择一个随机单元格。

以下是建议的代码:

start = (random.randint(0, self.width-1), random.randint(0, self.height-1))
self.dungeon['up_stairs'] = start

current = start
frontier = set()
visited = set([start])
while len(visited) < 400:
    frontier.add(current)
    self.place_cell(current, is_wall=False)
    found = False
    while not found:
        choices = [(1, 0), (0, 1), (0, -1), (-1, 0)]
        random.shuffle(choices)
        for apos in choices:
            new = utils.tuple_add(current, apos)
            if not new in visited and self.on_map(new):
                found = True
                break
        if not found:
            # we can remove this cell from frontier as it is 
            # completely surrounded by visited cells
            frontier.discard(current)
            # pick a random other one to start from
            current = random.sample(frontier, 1)[0]
    current = new    
    visited.add(current)