我有一个二维数组中的对象,我想在顶部,左边,右边遍历这个对象,我想检查是否有一些循环或更好地制作一些封闭区域。请参阅此图片以获得更好的解释。
实际上我有一个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
答案 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');
}