'How do I use flood fill in a nested for loop to count the number of "rooms" in a 2d grid?

I'm trying to use a flood fill algorithm to count the number of "rooms" in a 2d grid. I have the algorithm already which is:

import sys

im = [list('...##########....................................'),
      list('...#........#....####..................##########'),
      list('...#........#....#..#...############...#........#'),
      list('...##########....#..#...#..........#...##.......#'),
      list('.......#....#....####...#..........#....##......#'),
      list('.......#....#....#......############.....##.....#'),
      list('.......######....#........................##....#'),
      list('.................####........####..........######')]

HEIGHT = len(im)
WIDTH = len(im[0])

def floodFill(image,x,y,newChar, oldChar = None):
        if oldChar == None:
            oldChar = image[y][x]
        if oldChar == newChar or image[y][x] != oldChar:
            return

        image[y][x] = newChar

        if y + 1 < HEIGHT and image[y + 1][x] == oldChar:
            floodFill(image, x, y + 1, newChar, oldChar)
        if y - 1 >= 0 and image[y - 1][x] == oldChar:
            floodFill(image, x, y - 1, newChar, oldChar)

        if x + 1 < WIDTH and image[y][x + 1] == oldChar:
            floodFill(image, x + 1, y, newChar, oldChar)
        if x - 1 >= 0 and image[y][x - 1] == oldChar:
            floodFill(image, x - 1, y, newChar, oldChar)
        return

def printImage(image):
    for y in range(HEIGHT):
        for x in range(WIDTH):
            sys.stdout.write(image[y][x])
        sys.stdout.write('\n')
    sys.stdout.write('\n')

What I'm trying to do is use a nested for loop to find the periods and run the algorithm, but I'm not sure how to successfully adjust the x and y coordinates as I run through the list. So far what I have is:

def loops(image):
    count = 0
    for i in image:
        for j in i:
            if j == '.':
                count += 1
                x =
                y =
                floodFill(image,x,y,'?',oldChar=None)

My question is, how do I find the x and y coordinate of the periods to place into my function?



Solution 1:[1]

You could use Python's built-in enumerate() function to determine the needed indices easily. You didn't ask, but I also suggest that you use its print() function to output the image instead of writing directly to sys.stdout. In addition to that, the whole function could be simplified by outputting a whole row at a time.

Here's your code with those modifications (along with some other formatting changes I made to make it more readable). Note that I don't think your loops() function is identifying the "rooms" correctly, but also don't think that was what you asked about.

img = [list('...##########....................................'),
       list('...#........#....####..................##########'),
       list('...#........#....#..#...############...#........#'),
       list('...##########....#..#...#..........#...##.......#'),
       list('.......#....#....####...#..........#....##......#'),
       list('.......#....#....#......############.....##.....#'),
       list('.......######....#........................##....#'),
       list('.................####........####..........######')]

HEIGHT = len(img)
WIDTH = len(img[0])

def floodFill(image, x, y, newChar, oldChar=None):
        if oldChar == None:
            oldChar = image[y][x]
        if oldChar == newChar or image[y][x] != oldChar:
            return

        image[y][x] = newChar

        if y+1 < HEIGHT and image[y+1][x] == oldChar:
            floodFill(image, x, y+1, newChar, oldChar)
        if y-1 >= 0 and image[y-1][x] == oldChar:
            floodFill(image, x, y-1, newChar, oldChar)

        if x+1 < WIDTH and image[y][x+1] == oldChar:
            floodFill(image, x+1, y, newChar, oldChar)
        if x-1 >= 0 and image[y][x-1] == oldChar:
            floodFill(image, x-1, y, newChar, oldChar)
        return

def printImage(image):
#    for y in range(HEIGHT):
#        for x in range(WIDTH):
#            print(image[y][x], end='')
#        print()
#    print()
    for row in image:
        print(''.join(row))

def loops(image):
    count = 0
    for y, i in enumerate(image):
        for x, j in enumerate(i):
            if j == '.':
                count += 1
                floodFill(image, x, y, '?', oldChar=None)

loops(img)
printImage(img)

Results:

???##########????????????????????????????????????
???#????????#????####??????????????????##########
???#????????#????#??#???############???#????????#
???##########????#??#???#??????????#???##???????#
???????#????#????####???#??????????#????##??????#
???????#????#????#??????############?????##?????#
???????######????#????????????????????????##????#
?????????????????####????????####??????????######

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1