Классы ооп. Алгоритм flood fill.

Автор
avatar-josephjoseph
Notebook

Подход к реализации классов ооп. Алгоритм flood fill.

Под классом будем понимать mutable struct, в которую добавлены методы в качестве полей. Первый аргумент каждого метода (кроме конструктора) - это объект класса.

Класс Room.

In [ ]:
using Plots

mutable struct Room
    width
    height
    plane
    z
    set_walls
    draw
    floodfill
    animatedfloodfill
    robot
    function Room(x, y)
        plane = zeros(x,y);
        plane[[1, x], :] .= 1;
        plane[:, [1, y]] .= 1;
        function set_walls(r)
            println("set_walls body")
            println("width  ", string(r.width))
            println("height ", string(r.height))
            for i in 1:(r.width / 2)
                x1 = rand(1:r.width)
                y1 = rand(1:r.height)
                y2 = rand(1:r.height)
                if y1 < y2
                    for j in y1:y2
                        r.plane[x1, j] = 1
                    end
                end
            end
            for i in 1:(r.height / 2)
                x1 = rand(1:r.width)
                x2 = rand(1:r.width)
                y1 = rand(1:r.height)
                if x1 < x2
                    for j in x1:x2
                        r.plane[j, y1] = 1
                    end
                end
            end
        end
        function floodfill(r::Room, x, y, animated::Bool=false, A=0)
            if (x < 1 || x > r.width || y < 1 || y > r.height) return; end;
            if (r.plane[x, y] != 0 || r.z[x, y] != 0) return; end;
            r.z[x, y] = 0.5
            if animated
                heatmap(RGB.(r.robot.plane, r.z, r.z) + RGB.(r.z, r.plane, r.z), cbar = :none, c = :blues)
                heatmap!(title = "V1.1 Start point: " * "(" * string(r.robot.start_x) * "," * string(r.robot.start_y) * ")")
                frame(A)
            end
            floodfill(r, x - 1, y, animated, A)
            floodfill(r, x + 1, y, animated, A)
            floodfill(r, x, y - 1, animated, A)
            floodfill(r, x, y + 1, animated, A)
        end
        function draw(r::Room)
            A = Animation()
            heatmap(RGB.(r.robot.plane, r.z, r.z) + RGB.(r.z, r.plane, r.z), cbar = :none, c = :blues)
            heatmap!(title = "V1.1 Start point: " * "(" * string(r.robot.start_x) * "," * string(r.robot.start_y) * ")")
            frame(A)
            gif(A, "room.gif", fps = 10)
        end
        function animatedfloodfill(r::Room)
            A = Animation()
            r.z = zeros(x, y)
            r.floodfill(r, r.robot.start_x, r.robot.start_y, true, A)
            gif(A, "roomA.gif", fps = 30)
        end
        new(x, y, plane, zeros(x, y), set_walls, draw, floodfill, animatedfloodfill)
    end
end

Класс Robot.

In [ ]:
mutable struct Robot
    start_x
    start_y
    plane
    room
    function Robot(r::Room)
        x = size(r.plane,1)
        y = size(r.plane,2)
        gen_start_point = true
        s_x = 0
        s_y = 0
        while gen_start_point
            s_x = rand(1:x);
            s_y = rand(1:y);
            if r.plane[s_x, s_y] == 0
                gen_start_point = false
            end
        end
        plane = zeros(x,y);
        plane[s_x, s_y] = 1
        robot = new(s_x, s_y, plane, r)
        r.robot = robot
    end
end

Сценарий работы робота.

Создаем комнату:

In [ ]:
room = Room(100, 100)
room.set_walls(room)
set_walls body
width  100
height 100

Создаем робота в комнате:

In [ ]:
Robot(room)
println("Starting point: ", room.robot.start_x," ", room.robot.start_y)
Starting point: 79 91

Определяем область доступности для робота с помощью алгоритма flood fill:

In [ ]:
room.floodfill(room, room.robot.start_x, room.robot.start_y)
room.draw(room)
[ Info: Saved animation to /user/room.gif
Out[0]:
No description has been provided for this image

Далее показана работа алгоритма по-шагам:

In [ ]:
room.animatedfloodfill(room)
[ Info: Saved animation to /user/roomA.gif
Out[0]:
No description has been provided for this image