使用递归方法查找关闭路径或区域

时间:2014-09-16 11:31:58

标签: algorithm recursion lua corona

我有一个二维数组中的对象,我想在顶部,左边,右边遍历这个对象,我想检查是否有一些循环或更好地制作一些封闭区域。请参阅此图片以获得更好的解释。

enter image description here

实际上我有一个X x Y的插槽,当用户触摸任何一个区域时,它会在那里添加砖块,所以我想要做的是每次用户添加砖块检查它是否正在建立一个关闭路径。

我已经为此编写了递归函数,但它没有正常工作它总是只去顶部而不是左右。这是代码

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

编辑:新解决方案

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

2 个答案:

答案 0 :(得分:0)

实现的结构不会递归到其他方向,因为只调用第一个分支;应该包括所有邻居。显然,您尝试在阵列上实现一种Deph-first search。这种方法看起来绝对正确,但必须考虑细胞的所有邻居。或许最有帮助的是进行连通分量分析并填充所有接触边界的连通分量。

答案 1 :(得分:0)

<强> EDITED
相反,如果在黑色细胞的帮助下进行搜索,我们应该使用白色细胞进行搜索,因为您的目标是找到被黑色细胞束缚的区域,即使是对角线相邻的区域。我们应该找到一组白色单元,它们只有黑色单元格,而不是整个主网格的边界。这应该满足你的目的。

JS小提琴: http://jsfiddle.net/4d4wqer2/

这是我提出的修订算法:

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

使用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小提琴: http://jsfiddle.net/4d4wqer2/