MrAlmonds
MrAlmonds

Reputation: 38

Recursive Flood Fill - Checking Boundries

I Have a recursive flood fill of legal neighbours in matrix ( legal neighbour is a neighbour with same color), the flood is not filling all the legal neighbours in the array. the board I`m using for testing is :

int[][] map={{4,0,0,0},
             {0,4,0,0},
             {0,4,0,0},
             {0,4,0,0}};

   fill(map,1,1,9,4);// calling to function.

the output is :

4000
0900
0900
0900

Edit If i`m changing the map to:

int[][] map={{4,0,0,0},
         {4,4,0,0},
         {0,4,0,0},
         {0,4,0,0}};

The output will be:

4000
4900
0900
0900

The two left 4 number need to be filled too. and my recursive function is :

public static void fill(int[][] map, int row, int col, int color,int oldColor) 

   {

System.out.println("row is: "+row+"col is:"+col);
if ((row <= 0) || (row >= map.length) || (col <= 0) || (col >= map.length) ) return; 

if(map[row][col]==color)
        return;

if(map[row][col]==oldColor)
    {
        map[row][col]=color;
    }
if(col+1<=map.length)
      fill(map, col+1, row,color,oldColor);
 if((col-1)<=0) 
      fill(map,col-1, row,color,oldColor);

  if(row+1<=map.length)
      fill(map, col, row+1,color,oldColor);
  if((row-1)<=0)
      fill(map, col, row-1,color,oldColor);

   } 

Changing the code

public static void fill(int[][] map, int row, int col, int color,int oldColor) {
    System.out.println("row is: "+row+"col is:"+col);
if ((row < 0) || (row > map.length) || (col < 0) || (col > map.length) || map[row]                        [col]!=oldColor ) return; 

if(map[row][col]==color)
        return;

if(map[row][col]==oldColor)
    {
        map[row][col]=color;
    }

fill(map, col, row-1,color,oldColor);
fill(map, col+1, row,color,oldColor);
    fill(map, col, row+1,color,oldColor);
    fill(map,col-1, row,color,oldColor);
  }

The output is now:

9000
9900
0900
0400

Upvotes: 0

Views: 4135

Answers (2)

philippe lhardy
philippe lhardy

Reputation: 3286

This is not best answer, but i can't delete my submission.

public class Fill
{

    public static void fill(int[][] map, int col, int row, int color,int oldColor) 
    {

        System.out.println("row is: "+row+"col is:"+col);
        if ((row <= 0) || (row >= map.length) || (col <= 0) || (col >= map.length) ) return; 

        if(map[row][col]==color)
            return;

        if(map[row][col]==oldColor)
        {
            map[row][col]=color;
        }

        if(col+1<=map.length) {
            fill(map, col+1, row,color,oldColor);
        }

        if((col-1)<=0) { 
            fill(map,col-1, row,color,oldColor);
        }

        if(row+1<=map.length) {
            fill(map, col, row+1,color,oldColor);
        }

        if((row-1)<=0) {
            fill(map, col, row-1,color,oldColor);
        }

    } 


    public static void main(String pArgs[])
    {
        int[][] map={{4,0,0,0},
             {0,4,0,0},
             {0,4,0,0},
             {0,4,0,0}};

        printMap(map);
        fill(map,1,1,9,4);// calling to function.
        printMap(map);
    }

    static void printMap(int[][] map)
    {
        for (int i=0; i < 4; i++) {
            System.out.print("{");
            for (int j=0; j<4; j++) {
                System.out.print( map[i][j] + "," );
            }
            System.out.println("}");
        }
    }
}

Upvotes: 0

Roger Lindsj&#246;
Roger Lindsj&#246;

Reputation: 11543

You have several mistakes. First of all, your guard excludes row 0 and column 0, so that's one reason why you don't get the result you expect.

Now, fixing that you will get a stack overflow since you will try to fill all neighbours, no matter which color they have. That means that you will visit all cells with color 0 forever. You only want to fill neighbours that have the oldColor.

Last, your method expects the arguments row, column, but you recursivly call it with column, row, so you switch the indexes for each stack level.

Fixing that you can get a simpler method without a guarding if. If you expect different length on your rows, then you need to add the guard again.

Showing with a self contained example that prints the maps before and after filling them.

public class FloodFill {

  static int[][] map1 ={{4,0,0,0}, {4,4,4,4}, {0,4,0,4}, {0,4,0,0}};
  static int[][] map2 ={{0,4,4,4}, {0,4,0,4}, {0,4,0,4}, {9,9,9,4}};

  public static void fill(int[][] map, int row, int col, int color, int oldColor) {
    if (map[row][col] == oldColor) {
      map[row][col] = color;
      if (col + 1 < map[row].length)
        fill(map, row, col + 1, color, oldColor);           
      if (col > 0)
        fill(map, row, col - 1, color, oldColor);           
      if (row + 1 < map.length)
        fill(map, row + 1, col, color, oldColor);
      if (row > 0)
        fill(map, row - 1, col, color, oldColor);
    }
  }

  public static void main(String[] args) {
    floodfill(map1);
    floodfill(map2);
  }

  private static void floodfill(int[][] map) {
    show(map, "Initial");
    fill(map, 1, 1, 9, 4);
    show(map, "Filled");
  }

  private static void show(int[][] map, String label) {
    System.out.println(label);
    for (int[] row : map) {
      for (int val : row) {
        System.out.print(val + " ");
      }
      System.out.println();
    }
  }
}

An alternative fill with a guard which then also handles rows with different lengths.

public static void fill2(int[][] map, int row, int col, int color, int oldColor) {
  if (row < 0 || row >= map.length || col < 0 || col >= map[row].length) 
    return;
  if (map[row][col] == oldColor) {
    map[row][col] = color;
    fill2(map, row, col + 1, color, oldColor);          
    fill2(map, row, col - 1, color, oldColor);          
    fill2(map, row + 1, col, color, oldColor);
    fill2(map, row - 1, col, color, oldColor);
  }
}

Upvotes: 1

Related Questions