Find a close path or area with a recursive method

I have an object in a 2d array and I want to go through them from top, left, right for that object. I want to check if there is some kind of loop or is it better to make some kind of closed area. See this image for a better explanation.

enter image description here

Acutally I have an X x Y slot and when the user touches any area it adds a brick there, so I want the user to add a brick check every time if he makes a close path.

I have a recursive write function for this, but it doesn't work fine, it always only goes to the top and not to the right and left. Here is the code

function checkTrap(y,x)

if all_tiles[y][x].state == "changed" then --if brick is added at that location

 last_move_y = y
 last_move_x = x

  --check for top
  y = y - 1
  if( y >= 1 and y <= 6 and (last_move_y ~= y or last_move_x ~= x) ) then
    print("Moved to top at"..y..", "..x)
    return checkTrap(y, x)
  end
  --check for bottom
  y = y + 1
  if( y >= 1 and y <= 6 and (last_move_y ~= y or last_move_x ~= x) ) then
    print("Moved to bottom at"..y..", "..x)
    return checkTrap(y, x)
  end
  --check for left
  x = x - 1
  if( x >= 1 and x <= 6 and (last_move_y ~= y or last_move_x ~= x) ) then
    print("Moved to left at"..y..", "..x)
    return checkTrap(y, x)
  end
  --check for right
  x = x + 1
  if( x >= 1 and x <= 6 and (last_move_y ~= y or last_move_x ~= x) ) then
    print("Moved to right at"..y..", "..x)
    return checkTrap(y, x)
  end        

elseif all_tiles[y][x] == object then
  print("it a loop"..y..", "..x)
  return true;

else
  print("not changed")
  return false
end

end

      

Edit: new solution

function findClosedRegion()
              local currFlag,  isClose = -1, false

              local isVisited = {
                {-1, -1, -1, -1, -1, -1},
                {-1, -1, -1, -1, -1, -1},
                {-1, -1, -1, -1, -1, -1},
                {-1, -1, -1, -1, -1, -1},
                {-1, -1, -1, -1, -1, -1},
                {-1, -1, -1, -1, -1, -1}}


              local k, m = 1, 1

              while k <= 6 and not isClose
              do
                print("K "..k)
                while m <= 6 and not isClose
                do
                  print("M "..m)
                  if not isBrick[k][m] and isVisited[k][m] == -1 then

                  local cellsi = Stack:Create()
                  local cellsj = Stack:Create()

                    cellsi:push(k)
                    print("Pushed k "..k)

                    cellsj:push(m)
                    print("Pushed m "..m)

                    currFlag = currFlag + 1
                    isClose = true

                    while cellsi:getn() > 0 and isClose do

                      local p = cellsi:pop()
                      print("Pop p "..p)

                      local q = cellsj:pop()
                      print("Pop q "..q)

                      if( p >= 1 and p <= 6 and q >= 1 and q <= 6 ) then
                        if(not isBrick[p][q]) then
                          print("white ")
                          if(isVisited[p][q] == -1) then
                            print("invisited")
                            isVisited[p][q] = currFlag

                             cellsi.push(p - 1)
                             cellsj.push(q)

                             cellsi.push(p + 1)
                             cellsj.push(q)

                             cellsi.push(p)
                             cellsj.push(q + 1)

                             cellsi.push(p)
                             cellsj.push(q - 1)

                            cellsi:list()
                          else
                            if(isVisited[p][q] < currFlag) then
                              print("visited < currFlag")
                              isClose = false
                            end
                          end
                        end
                      else
                        isClose = false
                      end --p and q if ends here
                    end -- tile while end
                  else
                  --print("changed and not -1")
                  end
                  m = m + 1
                end -- m while end
                if(isClose) then
                  print("Closed path")
                end
                m = 1
                k = k + 1
              end -- k while end
            end

      

+3


source to share


2 answers


The implementation structure is ignored in other directions, as only the first branch is named; anyway, all neighbors should be included. Obviously you are trying to implement your Deph-first search array on your array. The approach seems absolutely right, but all the neighbors of the cell must be taken into account. Most likely, this will help to do the analysis of the connected components and fill in all the connected components that touch the boundary.



0


source


EDITED :
Instead, if we search with black cells, we should be looking for white cells, because your goal is to find an area linked by black cells, even if it's diagonally. We need to find a group of white cells that are limited only by black cells, and not by the border of the entire main grid. This should satisfy your purpose.

JS Fiddle: http://jsfiddle.net/4d4wqer2/

This is the reworked algorithm I came across:

for each cell and until closed area not found
     if white and visitedValue = -1
        push cell to stack
        while stack has values and closed area not found
            pop cell from stack
            if invalid cell // Cell coordinates are invalid
                this area is not closed, so break from the while
            else
                if white
                    if visitedValue = -1
                    {
                        mark visited
                        push neighboring four cells to the stack
                    }
                    else
                        if visitedValue > currVisitNumber // The current cells are part of previous searched cell group, which was not a closed group.
                            this area is not closed, so break from the while
if closed area found
    show message

      



Coded with JQuery:

    function findArea() {
        var currFlag = -1, isvisited = [], isClosed = false;
        for (var k = 0; k < rows; k++) {  // Initialize the isvisited array
            isvisited[k] = [];
            for (var m = 0; m < cols; m++)
                isvisited[k][m] = -1;
        }
        for (var k = 0; k < rows && !isClosed; k++)
            for (var m = 0; m < cols && !isClosed; m++) {
                if (!isblack[k][m] && isvisited[k][m] == -1) { // Unvisited white cell
                    var cellsi = [k], cellsj = [m];
                    currFlag++;
                    isClosed = true;
                    while (cellsi.length > 0 && isClosed) { // Stack has cells and no closed area is found
                        var p = cellsi.pop(), q = cellsj.pop();
                        if (p >= 0 && p < rows && q >= 0 && q < cols) { // The cell coord.s are valid
                            if (!isblack[p][q])
                                if (isvisited[p][q] == -1) {
                                    isvisited[p][q] = currFlag; // Mark visited
                                    cellsi.push(p - 1);         // Push the coord.s of the four adjacent cells
                                    cellsj.push(q);
                                    cellsi.push(p + 1);
                                    cellsj.push(q);
                                    cellsi.push(p);
                                    cellsj.push(q + 1);
                                    cellsi.push(p);
                                    cellsj.push(q - 1);
                                }
                                else
                                    if (isvisited[p][q] < currFlag) // The current group of white cells was part of a previous group of white cells which were found to be unbound by the black cells. So, skip this group.
                                        isClosed = false;
                        }
                        else
                            isClosed = false; // The current cell is out of border. Hence skip the whole group.
                    }
                }
            }
        if (isClosed)
            alert('Closed area found');
    }

      

JS Fiddle: http://jsfiddle.net/4d4wqer2/

0


source







All Articles