Как реализовать заливку в двумерном массиве в Юлии? - PullRequest
4 голосов
/ 13 января 2020

Проблема

Предположим, у меня есть двумерная матрица с некоторыми случайными целыми числами, равными 0 или 1. Как мне заполнить непрерывную область в моем массиве?

Этот алгоритм может особенно использоваться при обработке изображений для заливки цвета другим цветом в закрытой области, как инструмент заливки.

Пример

Предположим, мой массив:

1 0 1 1 1 1 0
0 0 1 1 1 1 1
0 0 0 1 1 1 1
0 1 0 0 0 1 1
0 0 0 1 1 1 1

Я хочу заполнить область 1 s в верхнем правом углу чем-то еще, например 8. Как мне это реализовать? Я знаю индексы любого 1 в этом регионе, и у меня есть индексы любого из 1 s.

После заполнения 8 s массив должен выглядеть следующим образом:

1 0 8 8 8 8 0
0 0 8 8 8 8 8
0 0 0 8 8 8 8
0 1 0 0 0 8 8
0 0 0 8 8 8 8 

Мои усилия:

Я пробовал следующие методы:

  • Проходя по каждому элементу в массиве, проверяя, является ли он 1, заменив его на 8. Очевидно, это не сработало, поскольку просто заменило все 1 на 8 s. Даже 1 s вне области были преобразованы в 8 s.
  • Используя относительные координаты, проверяя 1 s и заменяя на 8 s для начальных индексов, которые нам даны. Короче говоря, заменив всех соседей, значения которых 1, 8. Это также не сработало, поскольку оно заменило только 8 ближайших соседей и не заполнило область так, как я хотел.

1 Ответ

4 голосов
/ 13 января 2020

Вуаля! Ответ заключается в рекурсии:

Функция принимает ваш массив как arr, а координаты (или индексы) 1, которые вы знаете в виде кортежа (x, y), в качестве аргументов.

При использовании относительных координат мы вызываем функцию flood_fill для каждого из них:

function flood_fill(arr, (x, y))
    # check every element in the neighborhood of the element at (x, y) in arr
    for x_off in -1:1
        for y_off in -1:1
            # put the next part in a try-catch block so that if any index
            # is outside the array, we move on to the next element.
            try
                # if the element is a 1, change it to an 8 and call flood_fill 
                # on it so it fills it's neighbors
                if arr[x + x_off, y + y_off] == 1
                    arr[x + x_off, y + y_off] = 8
                    flood_fill(arr, (x + x_off, y + y_off))
                end
            catch
                continue
            end
        end
    end
end
...