可视化寻路算法

问题描述

我在 pygame 中做了一个寻路可视化工具,我几乎完成了,但我仍然不喜欢它的算法部分,事实上,当你按下可视化算法按钮时,它会向你显示最短路径黄色和算法访问过的所有节点都是浅蓝色,但它会立即向您显示,我希望它逐步为节点着色,以实际达到可视化的效果(如此处的 https://clementmihailescu.github.io/Pathfinding-Visualizer/#),我试图在函数中编写一些看起来可以按预期工作的代码,但没有,这是代码

# Breadth First Search Algorithm
def bfs(graph,start,goal):
    explored = []

    # Queue for traversing the
    # graph in the BFS
    queue = [[start]]

    # If the desired node is
    # reached
    if start == goal:
        return

    # Loop to traverse the graph
    # with the help of the queue

    while queue:
        path = queue.pop(0)
        node = path[-1]
        y,x = node
        # Codition to check if the
        # current node is not visited

        if node not in explored and nodes_rows[x][y].color is not BLACK:

            nodes_rows[x][y].color = LIGHT_BLUE
            neighbours = graph[node]

            # Loop to iterate over the
            # neighbours of the node
            for neighbour in neighbours:
                new_path = list(path)
                new_path.append(neighbour)
                queue.append(new_path)

                # Condition to check if the
                # neighbour node is the goal
                if neighbour == goal:
                    new_path.remove(start)
                    new_path.remove(goal)
                    return new_path

            explored.append(node)

    return None

nodes_rows[x][y].color == color_name 是负责为由字典表示的网格上的节点着色的代码(我提供了它是为了让您更容易理解着色在我的程序中的一般工作原理)。该实现的问题是,当我在 if 语句中添加着色部分来为所有邻居着色时,它会立即在网格上执行此操作,而不显示一种逐节点显示着色过程的动画,我的问题是我可以做它因此每次迭代都会为它们着色,而不是通过向此代码添加一些内容而不是一次编写一个代码,如果我确实需要编写一个代码,我该怎么做?

这就是我所说的像现在一样一次性着色的意思:

https://cdn.discordapp.com/attachments/772816508015083552/832303260911272046/PowerPoint_-_1_2021-04-15_20-13-35_Trim.mp4

编辑:

try:
    while True:
        if not ticks or pygame.time.get_ticks() - ticks >= 500:
           ticks = pygame.time.get_ticks()
           nodes = next(algorithm)
           if nodes_rows[nodes[-1][1]][nodes[-1][0]].color != BLUE:
              nodes_rows[nodes[-1][1]][nodes[-1][0]].color = LIGHT_BLUE
              pygame.display.update()
except stopiteration:
    pass

尝试用 yield 来做,如果我打印它,它会每半秒产生一个列表,最后有一个新的探索节点,但它在等待我尝试玩的总滴答数后立即更新display.update() 的缩进但没有工作,我什至不知道此时该怎么办

感谢所有提供帮助的人

解决方法

我认为问题在于您没有在 while queue 循环中更新画布。

程序将执行你的 bfs 算法,然后它会更新画布。

老实说,我不太经常使用 pygame,但我认为要强制画布重新绘制,您需要在 while 循环中插入 pygame.display.update()

,

根据上面的评论,这里有一个简单的生成器示例,可帮助您掌握想法。

def counter(x):
    for i in range(x):
        yield i
c = counter(3)
In: next(c)
Out: 0
In: next(c)
Out: 1
In: next(c)
Out: 2

发生的情况是每次调用 next 时,该函数都会继续运行,直到到达下一个 yield,此时它将返回产生的值。


它还会记住它停止的地方,所以下次你调用 next 时,函数会从它停止的地方继续。


在您的应用程序中,这可用于 yield 探索位置列表,然后以您喜欢的任何颜色绘制这些位置,调用 next(bfs) 前进并生成下一个探索位置列表,依此类推,直到您找到解决方案并用完要产出的项目。


再举一个例子,可能与您尝试做的事情更密切相关:

def make_path():
    path = []
    
    i = 0
    while True:
        path.append(i)
        i += 1
        yield path
        
c = make_path()

for _ in range(6):
    print(next(c))
Out: [0]
     [0,1]
     [0,1,2]
     [0,2,3]
     [0,3,4]
     [0,4,5]
,

Pygame 不是我的强项,但我认为您的项目中缺少一些东西:

1.- 您实际上无法控制屏幕上何时显示颜色。这可以通过以下方式实现:

branch_id

文档:https://devdocs.io/pygame/ref/display#pygame.display.update

通常在处理图形时,您会添加一种颜色,然后当您看到下一次屏幕绘制更新时,您必须做的是强制绘制,以便您可以安全地制作动画。

2.- 默认情况下不进行着色动画。 我不禁在您最初的问题中注意到这一点:“它会立即在网格上完成,而不会显示一种逐节点显示着色过程的动画”。如果您想要像上面链接的示例(寻路可视化器)那样的动画,恐怕您必须手动完成。尝试使用白色方块创建一个测试并开始在插值颜色内绘制生长圆圈,直到您到达墙壁并绘制完整的方块。这应该与您要完成的任务类似。

3.- 也许您应该在为画布设置动画时添加一些停止点。 硬件的刷新率比人眼快得多。 要正确查看着色动画,您应该尝试在插入颜色时添加执行停止。

<a data-toggle="modal" href="#myModal" class="btn btn-primary">Launch modal</a>

<div class="modal" id="myModal">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
          <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
          <h4 class="modal-title">Modal title</h4>
        </div><div class="container"></div>
        <div class="modal-body">
          Content for the dialog / modal goes here.
          <br>
          <br>
          <br>
          <br>
          <br>
          <a data-toggle="modal" href="#myModal2" class="btn btn-primary">Launch modal2</a>
          <div class="modal" id="myModal2" data-backdrop="static">
            <div class="modal-dialog">
                <div class="modal-content">
                  <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
                    <h4 class="modal-title">Second Modal title</h4>
                  </div><div class="container"></div>
                  <div class="modal-body">
                    Content for the dialog / modal goes here.
                  </div>
                  <div class="modal-footer">
                    <a href="#" data-dismiss="modal" class="btn">Close</a>
                    <a href="#" class="btn btn-primary">Save changes</a>
                  </div>
                </div>
              </div>
          </div>
        </div>
        <div class="modal-footer">
          <a href="#" data-dismiss="modal" class="btn">Close</a>
          <a href="#" class="btn btn-primary">Save changes</a>
        </div>
      </div>
    </div>
</div>

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.0.0/css/bootstrap.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.0.0/js/bootstrap.min.js"></script>

4.-(可选)平行绘画:使用线程。 如果这不适合您,请添加线程。 正如我之前所说,pygame 不是我的强项,但可以考虑添加线程来为每个正方形颜色设置动画。我在这里找到了一篇解释这个的帖子。

using threading in pygame

我希望这对您有所帮助并获得愉快的编码体验! :D