深度优先和广度优先搜索算法

BFS & DFS

# from __future__ import annotations
from abc import abstractmethod
from enum import IntEnum
# from typing import List, NamedTuple, Generic, Optional, TypeVar, Set
from typing import  NamedTuple, Optional
import matplotlib.pyplot as plt
import numpy as np
from utils import Stack,Queue


class Cell(IntEnum):
    EMPTY = 90     #入口出口障碍的颜色路径的颜色可走地方的颜色
    BLOCKED = 0
    START = 210
    END = 190
    PATH = 150


# class Color(IntEnum):
#     EMPTY = 0
#     BLOCKED = 255
#     START = 100
#     END = 200
#     FILL = 150


class MazeLocation(NamedTuple):
    row: int
    col: int



# T = TypeVar('T')
# # Generic[T]

class Maze():
    class _Node():
        def __init__(self, state, parent):            
            self.state = state
            self.parent = parent
            
            # self.cost = cost
            # self.heuristic = heuristic
            
            # self.state: T = state
            # self.parent: Optional[T] = parent
            # self.cost: float = cost
            # self.heuristic: float = heuristic

        # def __lt__(self, other: Maze._Node) -> bool:
        #     return (self.cost + self.heuristic) < (other.cost + other.heuristic)
    #构造函数,行 列 
    def __init__(self, rows: int = 10, cols: int = 10,
                 sparse: float = 0.2, seed: int = 365,
                 start: MazeLocation = MazeLocation(0, 0),
                 end: MazeLocation = MazeLocation(9, 9), *,
                 grid: Optional[np.array] = None) -> None:
        np.random.seed(seed)
        # self._start: MazeLocation = start
        # self._end: MazeLocation = end
        self._start: MazeLocation = start
        self._end: MazeLocation = end
        self.A = 0

        print('起点坐标是:{}'.format (self._start))
        if grid is None:
            #随机生成格子:                 #90              0
            self._grid = np.random.choice([Cell.BLOCKED, Cell.EMPTY],
                                                    (rows, cols), p=[sparse, 1 - sparse])
            # print(self._grid)
            # print(self._grid.tolist()[3][1])
        
        else:
            self._grid = grid
        
        #控制开始和结束节点格子的颜色
        self._grid[start] = Cell.START
        self._grid[end] = Cell.END

    def _test_goal(self, m1: MazeLocation) -> bool:
        return m1 == self._end
    
    def _success(self, m1):
        location = []
        #获取迷宫的格子行数列数
        row, col = self._grid.shape
        # print(row,col)
        
        if m1.row + 1 < row and self._grid[m1.row + 1, m1.col] != Cell.BLOCKED:
            location.append(MazeLocation(m1.row + 1, m1.col))           
        if m1.row - 1 >= 0 and self._grid[m1.row - 1, m1.col] != Cell.BLOCKED:
            location.append(MazeLocation(m1.row - 1, m1.col))
        if m1.col + 1 < col and self._grid[m1.row, m1.col + 1] != Cell.BLOCKED:
            location.append(MazeLocation(m1.row, m1.col + 1))
        if m1.col - 1 >= 0 and self._grid[m1.row, m1.col - 1] != Cell.BLOCKED:
            location.append(MazeLocation(m1.row, m1.col - 1))
        return location

    def _draw(self, pause: float) -> None:
        if self.A == 0:
            plt.title('Depth First Search')
        else:
            plt.title("Bread thFirst Search")
        plt.imshow(self._grid, cmap='rainbow', interpolation='nearest')
        plt.xticks([])
        plt.yticks([])
        plt.pause(interval=pause)
        plt.cla()

    def draw(self, colormap='rainbow') -> None:
        plt.close()
        fig, ax = plt.subplots()
        ax.imshow(self._grid, cmap=colormap)
        ax.set_xticks([])
        ax.set_yticks([])
        if self.A == 0:
            plt.title("DFS")
        else:
            plt.title("BFS")    
        plt.show()

    # @abstractmethod
    # def _search(self) -> Optional[Maze._Node]:
    #     """查找路径"""

    def show_path(self, pause: float = 0.5, *, plot: bool = True) -> None:
        if pause <= 0:
            raise ValueError('pause must be more than 0')
        path = self._search()
        # print(type(self._search()))
        if path is None:
            print('没有找到路径')
            return
        path = path.parent
        while path.parent is not None:
            self._grid[path.state] = Cell.PATH
            if plot:
                self._draw(pause)
            path = path.parent

        print('Path Done')

# 深度优先
class DepthFirstSearch(Maze):
    def _search(self):
        #用来记录状态
        self.A = 0
        
        #实例化一个栈对象
        stack = Stack()  
        
        #初始化起点
        initial = self._Node(self._start, None)
        # print(self._start)
        
        #标记走过的节点
        marked = {initial.state}
        
        #把出初始节点压入stack
        stack.push(initial)
        
        #当栈stack不为空的时候
        while stack:                      
            #父节点为stack中的最后一个元素
            parent = stack.pop()

            #当前节点
            state  = parent.state
            
            #检查当前节点是否是终点(目标节点)
            if self._test_goal(state):
                return parent
            
            children = self._success(state)
            for child in children: 
                # print(child)              
                if child not in marked:
                    marked.add(child)
                    stack.push(self._Node(child, parent))

#广度优先
class BreadthFirstSearch(Maze):
    def _search(self):
        self.A = 1
        queue = Queue()
        initial: BreadthFirstSearch._Node = self._Node(self._start, None)
        marked: Set[MazeLocation] = {initial.state}
        queue.push(initial)
        while queue:
            parent: DepthFirstSearch._Node = queue.pop()
            state: MazeLocation = parent.state
            if self._test_goal(state):
                return parent
            children: List[MazeLocation] = self._success(state)
            for child in children:
                if child not in marked:
                    marked.add(child)
                    queue.push(self._Node(child, parent))



if __name__ == "__main__":
    #深度优先:rows 行数  cols 列数  sparse 障碍的多少  
    # maze = DepthFirstSearch(rows=25, cols=25, sparse = 0.2, start=MazeLocation(24,24), end=MazeLocation(12,13), seed=50)
    
    #宽度优先
    maze = BreadthFirstSearch(rows=500, cols=500, sparse = 0.5, start = MazeLocation(499,499), end=MazeLocation(0, 0), seed=50)
    maze.show_path(0.001, plot=True)
    maze.draw()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值