【问题标题】:Find close path or region using recursive method使用递归方法查找关闭路径或区域
【发布时间】:2014-11-10 03:16:48
【问题描述】:

我有一个二维数组中的对象,我想在该对象的顶部、左侧、右侧遍历它们,实际上我想检查是否有一些循环或更好地创建一些封闭区域。请参阅这张图片以获得更好的解释。

实际上,我有一个 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

【问题讨论】:

    标签: algorithm recursion lua coronasdk


    【解决方案1】:

    实现的结构不会递归到其他方向,因为只调用了第一个分支;不知何故,所有邻居都应该包括在内。显然你试图在你的数组上实现一种Deph-first search。该方法似乎绝对正确,但必须考虑到单元格的所有邻居。可能最有帮助的是进行连通分量分析并填充所有接触边界的连通分量。

    【讨论】:

    • 您说实现的结构不是递归的,您能否建议任何更改以使这种方法有效。
    • 我对Lua的了解充其量是肤浅的;函数checkTrap 的返回类型(非正式意义上)是什么?
    • checkTrap 返回布尔值
    • 那么递归调用不应立即返回其调用的值,而是应将结果存储起来,并将所有结果通过andor组合起来。
    【解决方案2】:

    已编辑
    相反,如果在黑色单元格的帮助下进行搜索,我们应该使用白色单元格进行搜索,因为您的目标是找到由黑色单元格包围的区域,即使对角相邻。我们应该找到一组仅与黑色单元格相邻的白色单元格,而不是整个主网格的边界。那应该满足你的目的。

    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/

    【讨论】:

    • 您好,感谢您的帮助,但代码无法正常工作。在像 [1 ,2 ,3],[4, 5, 6],[7, 8, 9] 这样的场景中,如果我在位置 5 处触摸,那么在 7 处,这表示这是一个循环。希望你明白我想在这里表达什么?
    • 嗨,我已经尝试过你的新算法,但它不起作用,请看我编辑
    猜你喜欢
    • 2013-03-14
    • 1970-01-01
    • 2011-04-22
    • 2015-03-11
    • 2017-09-24
    • 1970-01-01
    • 2016-05-23
    • 2020-02-14
    • 1970-01-01
    相关资源
    最近更新 更多