采用递归与栈结合的方式实现迷宫分析与走迷宫(python3)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Kangyucheng/article/details/83934135

一、场景

1. General presentation

2.Examples

The file named maze_1.txt has the following contents.

二、题目分析

题目首先给了我们一个迷宫,要我门做两件事:

第一件事:分析迷宫

第二件事:在分析的基础上画迷宫

对于迷宫的分析:

所谓的迷宫只给了我们一些数字,数字的范围是0-3。

0:代表当前这个点与右边和下面都不相连;

1:代表这个点和和右面的点相连;

2:代表这个点和和下面的点相连;

3:代表这个点和下面与右面的点相连。

通过一个二维数组,可以将迷宫的墙确定下来。

在上图中,蓝色的线就是迷宫的墙,所给文件的第一个数字是1,所以在迷宫中,第一行的第一个点和第一行的第二个点相连。

第一件事:分析迷宫:分析六个数据

1.分析迷宫有多少个门,也可以说是迷宫有多少个入口。

2.分析迷宫有多少个墙体集合.

3.分析迷宫有多少不可达区域,也可以说有多少个死角块,也就是某一块是死的,从外面进不来.

4.分析迷宫中有多少个可达区域.

5.分析迷宫中有多少个红叉X

6.分析迷宫有多少条路径即图中黄色路线有多少条

第二件事:画图

1.画蓝线

2.画绿点

3.画红叉

4.画黄线

题目输入与输出要求

输入:

迷宫由数字的文件组成的.

输出:

1.六项分析结果

2.一个latex文件

迷宫的建立来自文件maze_1.txt:

    
   1  0  2  2  1  2  3  0     
    
   3  2  2  1  2  0  2  2     
    
   3  0  1  1  3  1  0  0     
    
   2  0  3  0  0  1  2  0     
    
   3  2  2  0  1  2  3  2     
    
   1  0  0  1  1  0  0  0     
    

 以上文件规定了墙体的连线.

三、编写代码

class MazeError(Exception):

    def __init__(self, value):
        self.value = value


class Road:
    up = True
    down = True
    left = True
    right = True
    is_border = False

    def __init__(self, up, down, left, right):
        self.up = up
        self.down = down
        self.left = left
        self.right = right


class Maze:
    file_name = ""
    model = [1, 2, 3, 0, "0", "1", "2", "3"]
    result = [0, 0, 0, 0, 0, 0, 0]  # 记录结果
    maze = list()  # 最初的迷宫
    b_maze = list()  # 扩大的迷宫
    road = list()  # 路径
    b_road = list()  # 扩大的路径

    viewed = list()  # 记录路的访问对应第5项
    viewed6 = list()  # 记录唯一路径的访问对应第6项
    viewed4 = list()  # 记录路的连通访问对应第4项
    viewed3 = list()  # 记录封闭点
    site_view = list()  # 记录点的访问

    entry = list()  # 记录死角个数
    death = 0  # 记录封闭路的个数
    death_list = list()  # 记录封闭路的起点

    success_path_start = list()  # 记录能够走出去的路径的起始点
    temp = list()  # 临时存储一条走出去的路径包括的点
    path = list()  # 存储所有路径的经过的点

    walls = list()  # 画图的墙
    pillars = list()  # 画图的点
    inner_points = list()  # 画X的块
    entry_exit_paths = list()  # 画路径

    def __init__(self, file_name):
        #  读取file到数组maze里面,存储所有墙体信息
        self.file_name = file_name
        file = open(file_name).readlines()
        for line in file:
            a = list()
            for i in line:
                if i in self.model:
                    a.append(i)
            if len(a) > 0:
                self.maze.append(a)
        # print(self.maze)
        # 检测maze是否满足条件
        self.check()
        # 扩大边界,和初始化点的访问
        for line in self.maze:
            b = list()
            b.append("0")
            x_site_view = list()
            x_site_view.append(False)
            for i in line:
                b.append(i)
                x_site_view.append(False)
            b.append("0")
            x_site_view.append(False)
            self.b_maze.append(b)

            self.site_view.append(x_site_view)
        tmp = list()
        for i in range(len(self.maze[0])):
            tmp.append(False)
        self.site_view.insert(0, tmp)
        self.site_view.append(tmp)
        self.b_maze.insert(0, ["0"] * len(self.b_maze[0]))
        self.b_maze.append(["0"]*len(self.b_maze[0]))

        # 根据墙体信息,设置路径信息
        # 以每个点的左上角的点为基准,读取其余影响该方格的点
        for y in range(len(self.maze)-1):
            x_line = list()

            for x in range(len(self.maze[0])-1):
                up = True
                down = True
                left = True
                right = True

                if self.maze[y][x] == '1':
                    up = False
                elif self.maze[y][x] == '2':
                    left = False
                elif self.maze[y][x] == '3':
                    up = False
                    left = False

                if self.maze[y+1][x] == "1" or self.maze[y+1][x] == "3":
                    down = False
                if self.maze[y][x+1] == "2" or self.maze[y][x+1] == "3":
                    right = False
                road = Road(up, down, left, right)
                x_line.append(road)

            self.road.append(x_line)

        # 扩大路径,并初始化路径的访问
        for y in self.road:
            x_line = list()
            road = Road(True, True, True, True)
            road.is_border = True
            x_line.append(road)
            for x in y:
                x_line.append(x)
            x_line.append(road)
            self.b_road.append(x_line)

        temp = list()
        for _ in self.b_road[0]:
            road = Road(True, True, True, True)
            road.is_border = True
            temp.append(road)

        self.b_road.insert(0, temp)
        self.b_road.append(temp)
        # 画图初始化
        self.pillars.append("% Pillars\n")
        self.inner_points.append("% Inner points in accessible cul-de-sacs\n")
        self.entry_exit_paths.append("% Entry-exit paths without intersections\n")

    def check(self):
        length = len(self.maze[0])
        for i in self.maze:
            if len(i) != length:
                raise MazeError("Incorrect input.")

        for i in self.maze[len(self.maze)-1]:
            if i in ["2", "3"]:
                raise MazeError("Input does not represent a maze.")
        for i in range(len(self.maze)):
            if self.maze[i][len(self.maze[0])-1] in ["3", "1"]:
                raise MazeError("Input does not represent a maze.")

    def init_road_view(self):
        self.viewed = list()
        self.viewed6 = list()
        self.viewed4 = list()
        self.viewed3 = list()
        for y in self.b_road:
            x_viewed = list()
            x_viewed6 = list()
            x_viewed4 = list()
            x_viewed3 = list()
            for _ in y:
                x_viewed.append(False)
                x_viewed6.append(False)
                x_viewed4.append(False)
                x_viewed3.append(False)
            self.viewed.append(x_viewed)
            self.viewed6.append(x_viewed6)
            self.viewed4.append(x_viewed4)
            self.viewed3.append(x_viewed3)

    def analyse(self):
        self.init_road_view()

        self.analyse_gates()  # 1
        self.analyse_wall_sets()  # 2
        self.analyse_sets()  # 5
        self.analyse_path()  # 6
        self.analyse_accessible_areas()  # 4
        self.analyse_inner_points()  # 3

        self.print_result()

    # 分析第一项:分析迷宫有多少个门
    def analyse_gates(self):
        # 分四条边考虑
        count = 0
        for i in self.road[0]:
            if i.up is True:
                count += 1
        for i in self.road[len(self.road)-1]:
            if i.down is True:
                count += 1
        for j in range(len(self.road)):
            if self.road[j][0].left is True:
                count += 1
            if self.road[j][len(self.road[0])-1].right is True:
                count += 1
        self.result[1] = count

    # 分析第二项:
    # 深度优先遍历
    def analyse_wall_sets(self):
        count = 0
        for y in range(1, len(self.b_maze)-1):
            for x in range(1, len(self.b_maze[0])-1):
                if self.site_view[y][x] is False:
                    if not self.is_inner(y, x):
                        count += 1
                    self.deep(y, x)

        self.result[2] = count

    def deep(self, y, x):
        if self.site_view[y][x] is True:
            return
        else:
            self.site_view[y][x] = True
            # 检测上面的线
            if self.b_maze[y-1][x] in ["2", "3"]:
                self.deep(y-1, x)
            # 检测左边的线
            if self.b_maze[y][x-1] in ["1", "3"]:
                self.deep(y, x-1)
            # 检测下面和右面的线
            if self.b_maze[y][x] == "1":
                self.deep(y, x+1)
            elif self.b_maze[y][x] == "2":
                self.deep(y+1, x)
            elif self.b_maze[y][x] == "3":
                self.deep(y+1, x)
                self.deep(y, x+1)
            else:
                return

    def is_inner(self, i, j):
        if self.b_maze[i][j] == '0' and self.b_maze[i - 1][j] in ['0', '1'] and self.b_maze[i][j - 1] in ['0', '2']:
            return True
        else:
            return False

    # 分析第三项:
    def analyse_inner_points(self):
        count = 0
        for i in self.death_list:
            self.go3(i[2], i[0], i[1])
        for line in self.viewed3:
            for i in line:
                if i is True:
                    count += 1

        for y in range(1, len(self.b_maze)-1):
            for x in range(1, len(self.b_maze[0])-1):
                if not self.not_death_block(y, x):
                    count += 1

        self.result[3] = count

    # 找到所有死角块
    def go3(self, direction, y, x):

        self.viewed3[y][x] = True
        next_y = y
        next_x = x
        if direction == "up":
            next_y = y-1
            next_x = x
        # 走右面
        elif direction == "right":
            next_y = y
            next_x = x + 1
        # 走下面
        elif direction == "down":
            next_y = y + 1
            next_x = x
        # 走左面
        elif direction == "left":
            next_y = y
            next_x = x - 1
            # self.go(direction, y, x - 1)
        # direction 代表当前点的出口的方向
        up = True
        down = True
        left = True
        right = True

        road = self.b_road[next_y][next_x]
        if direction == "right" or road.left is False:
            left = False
        if direction == "left" or road.right is False:
            right = False
        if direction == "up" or road.down is False:
            down = False
        if direction == "down" or road.up is False:
            up = False

        next_road = Road(up, down, left, right)
        next_direction = self.is_three_suround(next_road)

        if next_direction != "no":
            return self.go3(next_direction, next_y, next_x)
        elif next_road.up is False and next_road.down is False and next_road.left is False and next_road.right is False:
            self.viewed3[next_y][next_x] = True
            return

    # 分析第四项:共有多少个连通块
    def analyse_accessible_areas(self):

        count = 0
        for y in range(1, len(self.b_road)-1):
            for x in range(1, len(self.b_road[0])-1):
                if self.viewed4[y][x] is False:
                    if self.not_death_block(y, x):
                        count += 1
                    self.view(y, x)
        self.result[4] = count-self.death

    def not_death_block(self, y, x):
        # 不是四面的死角 返回True 是四面的死角返回False
        return self.b_road[y][x].up or self.b_road[y][x].down or self.b_road[y][x].left or self.b_road[y][x].right

    def view(self, y, x):
        if self.viewed4[y][x] is True:
            return
        self.viewed4[y][x] = True
        if not self.not_death_block(y, x):
            return
        else:
            if self.b_road[y][x].is_border is True:
                return
            else:
                # 四条路的判定与遍历
                if self.b_road[y][x].up is True:
                    self.view(y-1, x)
                if self.b_road[y][x].down is True:
                    self.view(y+1, x)
                if self.b_road[y][x].left is True:
                    self.view(y, x-1)
                if self.b_road[y][x].right is True:
                    self.view(y, x+1)

    # 分析第五项:共有多少个死角
    # 思路:深度优先遍历
    def analyse_sets(self):

        for y in range(1, len(self.b_road)-1):
            for x in range(1, len(self.b_road[0])-1):
                if self.viewed[y][x] is True:
                    continue
                direction = self.is_three_suround(self.b_road[y][x])
                if direction != "no":
                    b = self.go(direction, y, x)
                    if b is False:
                        self.death_list.append([y, x, direction])

        self.result[5] = len(self.entry)

    def go(self, direction, y, x):

        self.viewed[y][x] = True
        next_y = y
        next_x = x
        if direction == "up":
            next_y = y-1
            next_x = x
        # 走右面
        elif direction == "right":
            next_y = y
            next_x = x + 1
        # 走下面
        elif direction == "down":
            next_y = y + 1
            next_x = x
        # 走左面
        elif direction == "left":
            next_y = y
            next_x = x - 1
            # self.go(direction, y, x - 1)
        if self.b_road[next_y][next_x].is_border is True:
            self.entry.append([-2, -2, "end"])
            return True

        # direction 代表当前点的出口的方向
        up = True
        down = True
        left = True
        right = True

        road = self.b_road[next_y][next_x]
        if direction == "right" or road.left is False:
            left = False
        if direction == "left" or road.right is False:
            right = False
        if direction == "up" or road.down is False:
            down = False
        if direction == "down" or road.up is False:
            up = False

        next_road = Road(up, down, left, right)
        next_direction = self.is_three_suround(next_road)

        if next_direction != "no":

            return self.go(next_direction, next_y, next_x)
        elif self.is_two_surround(next_road):
            the_point = [next_y, next_x, direction]
            index = self.is_point_in_list(the_point)
            if index >= 0:
                # past_direction,direction是两个入口,转化成边之后即可与另一条边构成三环块,然后继续往下走
                past_direction = self.entry.pop(index)[2]

                the_direction = self.get_the_direction(past_direction, direction, next_y, next_x)
                # 找到出口,调用go方法
                if the_direction != "no":
                    self.go(the_direction, next_y, next_x)
            # 该点入list,并记录该点的已知入口
            else:
                self.entry.append(the_point)
            return True
        elif next_road.up is False and next_road.down is False and next_road.left is False and next_road.right is False:
            self.viewed[next_y][next_x] = True
            self.death += 1
            return False
        else:
            self.entry.append([next_y, next_x, "end"])
            return True

    def is_three_suround(self, road):
        count = 0
        direction = "no"
        if road.up is False:
            count += 1
        else:
            direction = "up"
        if road.down is False:
            count += 1
        else:
            direction = "down"
        if road.left is False:
            count += 1
        else:
            direction = "left"
        if road.right is False:
            count += 1
        else:
            direction = "right"

        if count == 3:
            return direction
        else:
            return "no"

    def is_two_surround(self,road):

        count = 0
        if road.up is False:
            count += 1
        if road.down is False:
            count += 1
        if road.left is False:
            count += 1
        if road.right is False:
            count += 1
        if count == 2:
            return True
        else:
            return False

    def is_point_in_list(self, point):
        b = -1
        for i in range(len(self.entry)):
            if self.entry[i][0] == point[0] and self.entry[i][1] == point[1] and self.entry[i][2] != "end":
                b = i
                break
        return b

    def get_the_direction(self, past_direction, direction, next_y, next_x):
        # 寻找出口
        up = True
        down = True
        left = True
        right = True
        if "up" in [past_direction, direction] or self.b_road[next_y][next_x].down is False:
            down = False
        if "down" in [past_direction, direction] or self.b_road[next_y][next_x].up is False:
            up = False
        if "right" in [past_direction, direction] or self.b_road[next_y][next_x].left is False:
            left = False
        if "left" in [past_direction, direction] or self.b_road[next_y][next_x].right is False:
            right = False
        road = Road(up, down, left, right)
        return self.is_three_suround(road)

    # 分析第六项:共有多少个连通路径
    def analyse_path(self):

        # 分四面进入,上面的就从上面进入,下面的就从下面进入,左面从左面进入。
        count = 0
        for x1 in range(1, len(self.b_road[0])-1):
            if self.viewed6[1][x1] is False and self.b_road[1][x1].up is True:
                if self.cross("up", 1, x1) is True:
                    self.success_path_start.append(["up", 1, x1])
                    count += 1

        n = len(self.b_road)-2
        for xn in range(1, len(self.b_road[0])-1):
            if self.viewed6[n][xn] is False and self.b_road[n][xn].down is True:
                if self.cross("down", n, xn) is True:
                    self.success_path_start.append(["down", n, xn])
                    count += 1

        for y1 in range(1, len(self.b_road)-1):
            if self.viewed6[y1][1] is False and self.b_road[y1][1].left is True:
                if self.cross("left", y1, 1) is True:
                    self.success_path_start.append(["left", y1, 1])
                    count += 1

        n2 = len(self.b_road[0])-2
        for yn in range(1, len(self.b_road) - 1):
            if self.viewed6[yn][n2] is False and self.b_road[yn][n2].right is True:
                if self.cross("right", yn, n2) is True:
                    self.success_path_start.append(["right", yn, n2])
                    count += 1

        self.result[6] = count

    def cross(self, direction, y, x):

        self.viewed6[y][x] = True

        up = True
        down = True
        left = True
        right = True

        if direction == "left" or self.viewed[y][x-1] is True or self.b_road[y][x].left is False:
            left = False
        if direction == "right" or self.viewed[y][x+1] is True or self.b_road[y][x].right is False:
            right = False
        if direction == "down" or self.viewed[y+1][x] is True or self.b_road[y][x].down is False:
            down = False
        if direction == "up" or self.viewed[y-1][x] is True or self.b_road[y][x].up is False:
            up = False

        road = Road(up, down, left, right)
        next_direction = self.is_three_suround(road)

        if next_direction != "no":
            n_direction = ""
            next_y = y
            next_x = x
            if next_direction == "up":
                next_y = y - 1
                next_x = x
                n_direction = "down"
                # self.go(direction, y - 1, x)
            # 走右面
            elif next_direction == "right":
                next_y = y
                next_x = x + 1
                n_direction = "left"
                # self.go(direction, y, x + 1)
            # 走下面
            elif next_direction == "down":
                next_y = y + 1
                next_x = x
                n_direction = "up"
                # self.go(direction, y + 1, x)
            # 走左面
            elif next_direction == "left":
                next_y = y
                next_x = x - 1
                n_direction = "right"
                # self.go(direction, y, x - 1)
            if self.b_road[next_y][next_x].is_border is True:
                return True
            else:
                return self.cross(n_direction, next_y, next_x)
        else:
            return False

    def cross2(self, direction, y, x):

        self.temp.append([x-0.5, y-0.5])

        up = True
        down = True
        left = True
        right = True

        if direction == "left" or self.viewed[y][x-1] is True or self.b_road[y][x].left is False:
            left = False
        if direction == "right" or self.viewed[y][x+1] is True or self.b_road[y][x].right is False:
            right = False
        if direction == "down" or self.viewed[y+1][x] is True or self.b_road[y][x].down is False:
            down = False
        if direction == "up" or self.viewed[y-1][x] is True or self.b_road[y][x].up is False:
            up = False

        road = Road(up, down, left, right)
        next_direction = self.is_three_suround(road)

        if next_direction != "no":
            n_direction = ""
            next_y = y
            next_x = x
            if next_direction == "up":
                next_y = y - 1
                next_x = x
                n_direction = "down"
            # 走右面
            elif next_direction == "right":
                next_y = y
                next_x = x + 1
                n_direction = "left"
            # 走下面
            elif next_direction == "down":
                next_y = y + 1
                next_x = x
                n_direction = "up"
            # 走左面
            elif next_direction == "left":
                next_y = y
                next_x = x - 1
                n_direction = "right"
            if self.b_road[next_y][next_x].is_border is True:
                self.temp.append([next_x-0.5, next_y-0.5])
                return True
            else:
                self.cross2(n_direction, next_y, next_x)
        else:
            return

    def go2(self, direction, y, x):

        self.viewed[y][x] = False
        next_y = y
        next_x = x
        if direction == "up":
            next_y = y-1
            next_x = x
            # self.go(direction, y - 1, x)
        # 走右面
        elif direction == "right":
            next_y = y
            next_x = x + 1
            # self.go(direction, y, x + 1)
        # 走下面
        elif direction == "down":
            next_y = y + 1
            next_x = x
            # self.go(direction, y + 1, x)
        # 走左面
        elif direction == "left":
            next_y = y
            next_x = x - 1
            # self.go(direction, y, x - 1)

        # direction 代表当前点的出口的方向

        up = True
        down = True
        left = True
        right = True

        road = self.b_road[next_y][next_x]
        if direction == "right" or road.left is False:
            left = False
        if direction == "left" or road.right is False:
            right = False
        if direction == "up" or road.down is False:
            down = False
        if direction == "down" or road.up is False:
            up = False

        next_road = Road(up, down, left, right)
        next_direction = self.is_three_suround(next_road)
        if next_direction != "no":
            self.go(next_direction, next_y, next_x)
        elif next_road.up is False and next_road.down is False and next_road.left is False and next_road.right is False:
            self.viewed[next_y][next_x] = False

    # 输出结果
    def print_result(self):
        # print(self.result)
        out_result = list()
        for i in range(1, 7):
            if self.result[i] == 0:
                out_result.append(str('no'))
            elif self.result[i] == 1:
                out_result.append(str('a'))
            else:
                out_result.append(str(self.result[i]))
        # 输出
        print("The maze has "+out_result[0]+" gates. ")
        print("The maze has "+out_result[1]+" sets of walls that are all connected.")
        print("The maze has "+out_result[2]+" inaccessible inner point.")
        print("The maze has "+out_result[3]+" unique accessible area.")
        print("The maze has "+out_result[4]+" sets of accessible cul-de-sacs that are all connected.")
        print("The maze has "+out_result[5]+" unique entry-exit path with no intersection not to cul-de-sacs. ")

    # 展示
    def display(self):
        tex_file_name = self.file_name.split('.')[0] + ".tex"

        tex_file = open(tex_file_name, 'w')
        head =["\\documentclass[10pt]{article}\n",
               "\\usepackage{tikz}\n",
                "\\usetikzlibrary{shapes.misc}\n",
                "\\usepackage[margin=0cm]{geometry}\n",
                "\\pagestyle{empty}\n",
                "\n",
                "\\tikzstyle{every node}=[cross out, draw, red]\n",
                "\n",
                "\\begin{document}\n",
                "\\vspace*{\\fill}\n",
                "\\begin{center}\n",
                "\\begin{tikzpicture}[x=0.5cm, y=-0.5cm, ultra thick, blue]\n",
                "% Walls\n"]
        border = ["\\end{tikzpicture}\n","\\end{center}\n","\\vspace*{\\fill}\n","\n","\\end{document}\n"]
        # 开始画墙
        for y in range(len(self.maze)):
            for x in range(len(self.maze[0])):
                if self.maze[y][x] in ["1", "3"]:
                    x1 = x+1
                    y1 = y
                    s = "    \\draw (" + str(x)+" ,"+str(y)+") -- ("+str(x1)+", "+str(y1)+");\n"
                    self.walls.append(s)
                if self.maze[y][x] in ["2", "3"]:
                    x1 = x
                    y1 = y+1
                    s = "    \\draw (" + str(x)+" ,"+str(y)+") -- ("+str(x1)+", "+str(y1)+");\n"
                    self.walls.append(s)
        # 开始画点
        for i in range(1, len(self.b_maze) - 1):
            for j in range(1, len(self.b_maze[0]) - 1):
                if self.is_inner(i, j):
                    s = "    \\fill[green] (" + str(j - 1) + "," + str(i - 1) + ") circle(0.2);\n"
                    self.pillars.append(s)
        # 开始画path
        for i in self.success_path_start:
            self.temp = list()
            if i[0] == "up":
                self.temp.append([i[2]-0.5, -0.5])
            elif i[0] == "down":
                self.temp.append([i[2]-0.5, len(self.b_road) - 1.5])
            elif i[0] == "left":
                self.temp.append([-0.5, i[1]-0.5])
            elif i[0] == "right":
                self.temp.append([len(self.b_road[0]) - 1.5, i[1]-0.5])

            self.cross2(i[0], i[1], i[2])
            self.path.append(self.temp)

        for i in self.path:
            for j in range(len(i)-1):
                s = "    \draw[dashed, yellow] ("+str(i[j][0])+","+str(i[j][1])+") -- ("+str(i[j+1][0])+","+str(i[j+1][1])+");\n"
                self.entry_exit_paths.append(s)

        # 开始画 X ,
        # 1.计算出所有的死块,设置viewed
        for i in self.death_list:
            self.go2(i[2], i[0], i[1])
        # 2.将所有visited中的点画上X
        for y in range(1, len(self.b_road)-1):
            for x in range(1, len(self.b_road[0])-1):
                if self.viewed[y][x] is True:
                    y1 = str(y-0.5)
                    x1 = str(x-0.5)
                    s = "    \\node at ("+x1+","+y1+") {};\n"
                    self.inner_points.append(s)

        tex_file.writelines(head)
        tex_file.writelines(self.walls)
        tex_file.writelines(self.pillars)
        tex_file.writelines(self.inner_points)
        tex_file.writelines(self.entry_exit_paths)
        tex_file.writelines(border)


my_maze = Maze('maze_1.txt')
my_maze.analyse()
my_maze.display()

猜你喜欢

转载自blog.csdn.net/Kangyucheng/article/details/83934135
今日推荐