[英]Searching for 'bubbles' in 2D array of chars in Java
我正在處理Go Game項目中的問題。
我有一個棋盤(goban),以2D字符數組表示。 在進行下一步操作之前,我想檢查數組中的“氣泡”。 Bubble應該是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 | + + + + + + + + + + + + + |
- - - - - - - - - - - - - - -
我想找到X的氣泡,將其計數並用'Z'代替。
我已經在Google上搜索了,我認為某些Connected-component標簽算法或FloodFill可以完成這項工作,但我不確定如何實現它。 這是解決問題的方法還是較簡單的方法? 謝謝
編輯:我試圖找到一些模式,可以找到特定角色的區域並計算其自由度,但是當位置多層時,它總是失敗。 更改數據結構可能是解決方案,但如果可能的話,我想照現在做。
我目前的解決方案是:
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
}
您可以使用遞歸方法(實際上是使用FloodFill理論)來做到這一點。
基本上,遍歷整個網格,每次找到一個X時,將其替換為Z及其4個鄰居(如果適用)。 但是訣竅是:與其再次替換它們而不必每次都循環,不如再次調用相同的(調用)方法來執行此操作。 遞歸將完成其余的工作。
這是它的(快速完成的)偽代碼版本:(假定網格的索引從0到xmax,從0到ymax)
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);
}
據我所知,這是解決此問題的唯一方法 ,無論泡沫形狀如何怪異,該方法都有效。 復雜度也不錯。
這可以進一步優化,因為它當前檢查顯然不再包含X的字符(因為它們剛剛被Z取代)。 這留給讀者練習:)
(注意: 掃雷游戲以及其他基於該解決方案的游戲)
這是我用於類似圖像分析需求的一種算法(偽代碼):
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);
基本上,您維護一組點的集合,其中每個點代表板上的連續點的“泡沫”。 掃描板上的每個位置,如果它是“ X”並且尚未存在於某個區域中,則創建一個新區域和一個包含該位置的堆棧,並且當堆棧中有任何項目時,請訪問其鄰居以尋找未訪問的“ X” ,將它們添加到新區域並按發現的順序堆疊。
最后,您將擁有一組點集,每個點集代表一個“氣泡”。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.