搜索';气泡';Java中字符的二维数组

搜索';气泡';Java中字符的二维数组,java,arrays,Java,Arrays,我正在处理围棋项目中的一个问题 我有一个棋盘(goban),由2D字符数组表示。在下一步行动之前,我想检查数组中是否有“气泡”。气泡应该是在4个方向上由另一组特定的相同字符包围的相同字符的4个连接区域。 如果存在此“气泡”,则应将其中的字符替换为其他字符。但可能会有更多的区域,而且并非所有区域都是封闭的。 例如,我有一个董事会: 1 2 3 4 5 6 7 8 9 10 11 12 13 - - - - - - - - - - - -

我正在处理围棋项目中的一个问题

我有一个棋盘(goban),由2D字符数组表示。在下一步行动之前,我想检查数组中是否有“气泡”。气泡应该是在4个方向上由另一组特定的相同字符包围的相同字符的4个连接区域。 如果存在此“气泡”,则应将其中的字符替换为其他字符。但可能会有更多的区域,而且并非所有区域都是封闭的。 例如,我有一个董事会:

      1  2  3  4  5  6  7  8  9  10 11 12 13
   -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
 A |  +  +  +  +  +  +  +  +  +  +  +  +  +  | 
 B |  +  +  +  +  +  +  +  +  +  +  +  +  +  | 
 C |  +  +  +  +  +  +  +  +  +  +  +  +  +  | 
 D |  +  +  +  +  +  +  +  +  +  +  +  +  +  | 
 E |  +  +  +  +  +  +  +  +  +  +  +  +  +  | 
 F |  +  +  O  O  O  O  +  +  +  +  +  +  +  | 
 G |  +  O  X  X  X  X  O  +  +  +  +  +  +  | 
 H |  +  +  O  O  X  X  O  +  +  +  +  +  +  | 
 I |  +  +  +  +  O  X  X  O  +  +  +  +  +  | 
 J |  +  +  +  +  O  X  O  +  +  +  +  +  +  | 
 K |  +  +  +  +  +  O  +  +  +  +  +  +  +  | 
 L |  +  +  +  +  +  +  +  +  +  +  +  +  +  | 
 M |  +  +  +  +  +  +  +  +  +  +  +  +  +  | 
   -  -  -  -  -  -  -  -  -  -  -  -  -  -  - 
我想找到Xs的气泡,数一数,然后用Z代替

我在谷歌上搜索过,我认为一些连接组件标记算法或泛洪填充可以完成这项工作,但我不确定如何实现它。这是解决问题的方法还是简单一点的方法? 多谢各位

编辑: 我试图找到一些模式,可以找到特定角色的区域并计算他们的自由度,但当位置是多层的时候,总是失败。 更改数据结构可能是解决方案,但如果可能的话,我希望现在就这样做

我当前的解决方案想法:

public void solve(){
if (boardContainsEnclosedAreas(goban, onMovePlayerStone, oppositePlayerStone){
    onMovePlayerScore += countElementsInAreaAndReplaceThem(onMovePlayerStone, 'Z');  
}
}

public boolean boardContainsEnclosedAreas(char[][] playingBoard, char searchedChar, char surroundingChar){
// this method should find the bubble in the playingBoard array
}

public int countElementsInAreaAndReplaceThem(char searchedChar, char replacingChar){
// the method should go through the bubble and replace all inner chars 
// returns amount of replaced chars
}
以下是一个算法(伪代码),我曾用于类似的图像分析需求:

regions = Collection<Set<Point>>
foreach (Point p : allBoardLocations)
  if (charAtLocation(p) != 'X') continue
  foundInRegion = false
  for (Set<Point> s : regions)
    if (s.contains(p))
      foundInRegion=true
      break;
  if (!foundInRegion)
    newRegion = new Set<Point>()
    stack = new Stack<Point>()
    stack.push(p)
    while (!stack.empty())
      foreach (Point n : neighboringPoints(stack.pop()))
        if (charAtLocation(n) == 'X')
          if (!newRegion.contains(n))
            newRegion.add(n);
            stack.push(n);
regions=集合
foreach(p点:所有板位置)
如果(字符位置(p)!=“X”)继续
foundInRegion=false
用于(集合s:区域)
如果(s.包含(p))
foundInRegion=true
打破
如果(!foundInRegion)
newRegion=新集合()
堆栈=新堆栈()
堆栈推送(p)
而(!stack.empty())
foreach(点n:相邻点(stack.pop()))
如果(字符位置(n)='X')
如果(!newRegion.contains(n))
添加(n);
堆栈推送(n);
基本上,您维护一组点,其中每一组点表示电路板上相邻点的“气泡”。扫描电路板上的每个位置,如果它是一个“X”,并且它不在某个区域中,则创建一个新区域和一个包含该位置的堆栈,当堆栈上有任何项目时,访问其邻居搜索未访问的“X”,并将其添加到新区域和发现的堆栈中


最后,您将拥有一组点,每个点代表一个“气泡”。

您可以使用递归方法,实际上是使用泛洪填充理论

基本上,在网格中运行,每次找到一个X时,用一个Z替换它,以及它的4个邻居(如果适用)。但诀窍是:不要只是替换它们,每次都必须再次循环,而是再次调用相同的(调用)方法。递归将完成其余的工作

下面是它的一个(快速完成的)伪代码版本: (假设网格的索引范围是从0到xmax,从0到ymax)

int numberOfBubbles=0;
对于(x=0到xmax){
对于(y=0到ymax){
if(getCharAt(x,y)=“x”){//if是必需的,因为你想计算气泡数。如果不是,你可以只做handlebble(x,y);
numberOfBubbles++;
手柄(x,y);
}
}
}
//递归方法
空心把手(内部x,内部y){
if(getCharAt(x,y)!=“x”){
return;//退出条件
}
getCharAt(x,y)=“Z”;
如果(x>0)手柄(x-1,y);
如果(x0)手柄(x,y-1);
如果(y
据我所知,这是解决这个问题的唯一办法,不管你的泡泡形状有多奇怪,它都能起作用。复杂性也不错

这可以进一步优化,因为它当前检查的字符显然不再包含X(因为它们刚刚被Z替换)。这是留给读者的练习:)


(注意:扫雷舰游戏基于该解决方案)

您考虑过其他数据结构吗?也许你可以有一个链类,它包含所有相同颜色的连接瓷砖。它将有一些自由度,当自由度达到0时,链将被删除。如果您也发布您的“期望输出”将非常好。谢谢大家,我已经更新了描述请求的任务更复杂:您首先必须确定是否要翻转某个区域中的X。嗯。你是说OP只对被O包围的X块感兴趣?描述中没有明确提到这一点(或者只是我)。这确实会使情况更加复杂。我会考虑一下。这可能仍然可以通过这种方法实现:在处理气泡时,如果发现相邻的字符既不是“X”也不是“O”,则停止进程并还原网格。这将确保只有被O包围的X泡泡完成这个过程,并翻转X。是的,或者不恢复更改,您可以只在内存中存储您可能必须更改的位置,并且只有在最后,如果您从未碰到空白方块,才这样做。在围棋规则中,如果您完全包围对手,您就“吃掉”他们的棋子。这是一个有趣的游戏,但我不擅长。规则比国际象棋简单得多,但实际上它是一种更复杂的游戏。@toto2:是的,谢谢,我只是有点从头顶上吐出来了。我确信它充满了错误,只是想证明这个想法。
int numberOfBubbles = 0;

for (x = 0 to xmax) {
    for (y = 0 to ymax) {
       if (getCharAt(x, y) == "X") { // this if is needed because you want to count the bubbles. If not, you could just do handleBubble(x, y);
           numberOfBubbles++;
           handleBubble(x, y);
       }
    }
}

// Recursive method
void handleBubble(int x, int y) {
    if (getCharAt(x, y) != "X") {
        return; // exit condition
    }

    getCharAt(x, y) = "Z";    
    if (x > 0) handleBubble(x-1, y);
    if (x < xmax) handleBubble(x+1, y);
    if (y > 0) handleBubble(x, y-1);
    if (y < ymax) handleBubble(x, y+1);
}