Buscar valores iguais e adjacentes em uma matriz

3 respostas
L

Tenho uma array bi-dimensional que utilizo para desenhar um mapa através de tiling.
Quero que, quando eu clicar em um determinado tile, o programa me retorne todos os tiles de mesmo id que estejam conectados.

Basicamente, quero fazer um "paint bucket" que substitua os tiles "grudados" por outros tiles.

Tenho o seguinte código:

private void getAdjacents(int x, int y) { if(x >= 0 && x < total_cols && y >= 0 && y < total_rows){ if(selectionArray[x][y] != 1 && map.getGroundTile(x, y).getId() == selectedID){ selectionArray[x][y] = 1; if(x <= tile_to_repaint[0]){ getAdjacents(x-1, y); } if(x >= tile_to_repaint[0]){ getAdjacents(x+1, y); } if(y <= tile_to_repaint[1]){ getAdjacents(x, y-1); } if(y >= tile_to_repaint[1]){ getAdjacents(x, y+1); } } } }

ele funciona perfeitamente, se todos os tiles no mapa tiverem o mesmo ID, porém a coisa complica um pouco com a seguinte situação:

se eu tenho

01100
10100
11100
00000

quando eu mando pegar os 1, ele me retorna as seguintes posições
0[color=cyan]11[/color]00
[color=red]1[/color]0[color=cyan]1[/color]00
[color=cyan]111[/color]00
00000

os que estão em azul são os retornados

como pode-se notar, um dos 1 é ignorado

se eu retiro as comparações <= e >= tile_to_repaint[0/1] tal problema desaparece, porem, com um mapa um pouco maior já ocorre um StackOverflowError
Imagino que seja porque o programa percorre as mesmas linhas e colunas muitas vezes (bem mais do que o necessário)

Por acaso alguem sabe de um código funcional que faça o que eu preciso? (ou tem uma sugestão que conserte esse erro?)

3 Respostas

ViniGodoy

Fica difícil te ajudar sem saber o que essas estruturas significam. Agora, esse é um algorítmo bastante comum, procure sua implementação na internet:



http://lodev.org/cgtutor/floodfill.html

L

ViniGodoy:
Fica difícil te ajudar sem saber o que essas estruturas significam. Agora, esse é um algorítmo bastante comum, procure sua implementação na internet:


http://lodev.org/cgtutor/floodfill.html

é, eu achei uns links falando sobre floodfill, que era exatamente o que eu queria

o problema é que a recursividade sempre me causa StackOverflow em arrays grandes demais

só pra esclarecer um pouco

x seria a coluna da matriz e y a linha, e selectionArray seria uma matriz de zeros e uns, que corresponderia aos tiles que seriam afetados pelo flood fill (representados por 1)
a comparação map.getGroundTile(x, y).getId() == selectedID verifica se o tile que estou vendo no momento é um dos que serão repintados,
ou seja, se cliquei num tile de ID = 1, eu vou checando se os que encontro tem mesmo ID

eu tentei utilizar um codigo que encontrei, mas ficou a mesma coisa no final das contas:

private void getAdjacents(int x, int y) { try { if(x &gt;= 0 && x &lt; total_cols && y &gt;= 0 && y &lt; total_rows ){ if(selectionArray[x][y] != 1 && map.getGroundTile(x, y).getId() == selectedID){ selectionArray[x][y] = 1; getAdjacents(x+1, y); getAdjacents(x, y+1); getAdjacents(x-1, y); getAdjacents(x, y-1); } } } catch (StackOverflowError e) { } }

com esse try/catch ele pinta quase tudo, mas ainda não é o que eu gostaria (e nem o melhor, creio eu)

será que o problema está na recursividade?

ViniGodoy

Não se dá try catch em errors.

E no link que te passei, ele descreve um algorítmo usando uma fila ou pilha, que evita o problema da recursividade.
O segundo link mostra um algorítmo otimizado, que evita processar 2 vezes o mesmo pixel.

Criado 11 de setembro de 2011
Ultima resposta 11 de set. de 2011
Respostas 3
Participantes 2