Find close path or region using recursive method

こ雲淡風輕ζ 提交于 2019-12-12 17:15:39

问题


I have a object in 2d array and i want to traverse through them top, left, right for that object acutally i want to check if there are making some loop or better making some closed region. See this picture for better explanation.

Acutally i have a X x Y of slot and when user touch on any of the region it adds the brick there so what i want to do is every time user add a brick check if it is making a close path.

I have writen recursive function for that but it's not working fine it always go for the top only and not 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's 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

回答1:


The structure of the implementation does not recurse into other directions as only the first branch is called; somehow all neighbors should be included. Apparently you try to implement a kind of Deph-first search on your array. The approach seems absolutely rightm, but all neighbors of a cell have to be taken into account. What perhaps would help most would be to do a connected component analysis and fill all the connected components which touch the border.




回答2:


EDITED:
Instead if searching with the help of black cells, we should search with white cells because your goal is to find area bound by black cells, even if diagonally adjacent. We should find a group of white cells which is only bordered by black cells and not by the border of the whole main grid. That should satisfy your purpose.

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

This is the revised algorithm I came up with:

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

Programmed using 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/



来源:https://stackoverflow.com/questions/25867647/find-close-path-or-region-using-recursive-method

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!