Home > other >  Python flood fill algorithm north, south, east, west
Python flood fill algorithm north, south, east, west

Time:04-23

I have a question about flood fill algorithms.

I would like to fill a given field that looks like this:

Field

The user should give the starting position

So far I made the below code, but it just fills up and down and I would like it to fill in all 4 directions.

#given field size and markers
number_of_columns = 20
number_of_rows = 10
filled_marker = "x"
empty_marker = " "


def create_grid(number_of_rows, number_of_columns):
    grid = []
    for row in range(number_of_rows):
        grid.append([])
        for column in range(number_of_columns):
            if row == 1 or row == 8 or column == 3 or column == 15:
                grid[row].append(filled_marker)
            else:
                grid[row].append(empty_marker)
    return grid


def print_grid(grid):
    for row in range(number_of_rows):
        for column in range(number_of_columns):
            print(grid[row][column], end="")
        print()


def get_user_input():
    start_row = int(input("Enter the start row: "))
    start_column = int(input("Enter the start column: "))
    return start_row, start_column


def flood_fill(grid, start_row, start_column):
    grid[start_row][start_column] = filled_marker
    print_grid(grid)
    if start_row > 0 and grid[start_row - 1][start_column] == empty_marker:
        flood_fill(grid, start_row - 1, start_column)
    if start_row < number_of_rows - 1 and grid[start_row   1][start_column] == empty_marker:
        flood_fill(grid, start_row   1, start_column)
    if start_column > 0 and grid[start_row][start_column - 1] == empty_marker:
        flood_fill(grid, start_row, start_column - 1)
    if start_column < number_of_columns - 1 and grid[start_row][start_column   1] == empty_marker:
        flood_fill(grid, start_row, start_column   1)


def main():
    grid = create_grid(number_of_rows, number_of_columns)
    start_row, start_column = get_user_input()
    flood_fill(grid, start_row, start_column)


main()

CodePudding user response:

I converted the recursive approach to an iterative approach using a a deque.

You will have to import collections at the start of your script.

def flood_fill(grid, start_row, start_column):
    locations = collections.deque()
    locations.append((start_row, start_column))

    while locations:
        row, column = locations.popleft()
        if grid[row][column] == empty_marker:
            grid[row][column] = filled_marker
            print_grid(grid)
        if row > 0 and grid[row - 1][column] == empty_marker:
            locations.append((row-1, column))
        if row < number_of_rows - 1 and grid[row   1][column] == empty_marker:
            locations.append((row 1, column))
        if column > 0 and grid[row][column - 1] == empty_marker:
            locations.append((row, column-1))
        if column < number_of_columns - 1 and grid[row][column   1] == empty_marker:
            locations.append((row, column 1))

The existing approach checked row - 1 first and then continued to work from there and that means that it now handled row - 1 again from the new location (so a full offset of -2 from the start) and so on.

Now we build a double ended qeue where we take the first element and add the neighbors of this element to the end of the queue if they match the constrictions. Then this task is repeated until the queue is empty.

  • Related