Neighbor search algorithm?

BlitzMax Forums/BlitzMax Programming/Neighbor search algorithm?

Bukky(Posted 2006) [#1]
Hey guys,

Here is what I am working with right now:



It is an array which consists of block objects. What I am trying to do is to seperate this into color coded regions, where each region consists of 3 more more touching blocks (but not diagonally).

For example, the red regions will be split up as such:

region 1:

[0, 0] [0, 1] [1, 0] [1, 1] [1, 2] [2, 1] [2, 2]

region 2:

[3, 0] [4, 0] [4, 2] [5, 0] [5, 1] [5, 2] [6, 1]

region 3:

[5, 5] [6, 5] [6, 6]

region 4:

[8, 9] [8, 10], [9, 7] [9, 8] [9, 9] [10, 9] [10, 10] [11, 9]

region 5:

[2, 12] [3, 12] [3, 13] [4, 13] [5, 13]

etc... for all of the other colors.

Anyone have any idea on how to do this?


SculptureOfSoul(Posted 2006) [#2]
How "intelligent" would you like this to be? I can only imagine it's going to be an order of magnitude more difficult to come up with the most efficient/most intelligent algorithm compared to a more 'hack' algorithm that gets the job done but is slower and 'stupider'.

Also, are there any rules besides moving each color so that it makes a grouping of 3? Is it desirable to try and make the largest groupings possible, given that doing so takes no more moves than not doing so. Please elaborate on any further rules or desirable/undesirable behavior.

Lastly, how often is this going to need to be calculated, and how fast do you need the calculation to be? I know I'd be able to offer more help if I knew what kind of guidelines I needed to work with.

Thanks :)


Dreamora(Posted 2006) [#3]
Look for HOSHEN - Koppelman (think was written like this) algorithm

should provide you with a very performatn solution for finding regions of same neighbors


SculptureOfSoul(Posted 2006) [#4]
Aww, trying to come up with your own algorithm is where the fun's at! :)

Actually, I usually try and come up with an algorithm for any problem, and only *then* see what's out there. Not only does this get you thinking, but this also lets you see how you approach the problem and then later reflect on how you can improve your approach to problems in general.


Kurator(Posted 2006) [#5]
i did this in purebasic some time ago, it is simply a recursive routine:

(srry for german variables)

VerarbeiteSpielfeld = Functionname
farbe = index of color
score = to count the amount of stones
entfernen = flag if selectet stones should be removed
hidden = flag if should be shown

i used 2 arrays - one for playing (Spielfeld[x,y] and a seconde one for showing Tips to Player (TipSpielfeld[x,y])


Procedure VerarbeiteSpielfeld(x.l, y.l, farbe.b, score.l, entfernen.b, versteckt.b)

  If x<0 Or x>#dim_x Or y<0 Or y>#dim_y Or TipSpielfeld(x,y) = -1 Or Spielfeld(x,y) = -1 
      
      ProcedureReturn score.l
  
  Else

    If versteckt.b = 0
      DisplayTransparentSprite(#gfx_tip,x*16+#offset_X,y*16+#offset_y)
    EndIf
    
    TipSpielfeld(x,y) = -1
    
    If entfernen.b = 1
      Spielfeld(x,y) = -1
      ;Debug "Lösche: "+Str(x)+"/"+Str(y)
    EndIf
    
    If y>0 And Spielfeld(x, y-1) = farbe And TipSpielfeld(x, y-1) <> -1 And Spielfeld(x,y-1) <> -1
      score = VerarbeiteSpielfeld(x, y-1, farbe, score+1, entfernen, versteckt.b)
    EndIf
    If x>0 And Spielfeld(x-1, y) = farbe And TipSpielfeld(x-1, y) <> -1 And Spielfeld(x-1,y) <> -1
      score = VerarbeiteSpielfeld(x-1, y, farbe, score+1, entfernen, versteckt.b)
    EndIf
     If y<#dim_y And Spielfeld(x, y+1) = farbe And TipSpielfeld(x, y+1) <> -1 And Spielfeld(x,y+1) <> -1
      score = VerarbeiteSpielfeld(x, y+1, farbe, score+1, entfernen, versteckt.b)
    EndIf   
    If x<#dim_x And Spielfeld(x+1, y) = farbe And TipSpielfeld(x+1, y) <> -1 And Spielfeld(x+1,y) <> -1
      score = VerarbeiteSpielfeld(x+1, y, farbe, score+1, entfernen, versteckt.b)
    EndIf
    
    ProcedureReturn score.l

  EndIf

EndProcedure




Jake L.(Posted 2006) [#6]
^ Looks like a default FloodFill. Works well unless you're checking big areas. Then you could run into stack-issues. Search Wikipedia for floodfill, there are links to non recursive versions.

For my puzzle game I use this recursive FF-Algo, too. Too lazy to write a listbased FF, but if anyone has one in store... ;)


Kurator(Posted 2006) [#7]
yes, recursion is nothing for big arrays :)


Dreamora(Posted 2006) [#8]
The naive approach on that problem, if not interested in see a potential way would be:

Check all fields for their neighbors and their own "nationality" and see if they are equal.
If yes: See if that neighbor field is part of a region. If so, join the region. If not, declare a new region for this and that neightbor

At least from the given problem that would how I would be doing it, especially as it looks nice and "doable" with more than only 2 dimensions :-)


skn3(Posted 2006) [#9]
.


Bukky(Posted 2006) [#10]
Thanks all for the info! I'll give your suggestions a try.


Bukky(Posted 2006) [#11]
Hey again.

I tried implementing the 'Flood Fill' algorithm from the Wikipedia article, and it was a lot easier than I had anticipated. Thanks for the suggestion! :)

There is one problem though....The program tends to crash when I search to the north and to the left O_o

Here is the code:


Method tesRegion(a_color$, x_coord%, y_coord%, region_num%)
		If Container[x_coord, y_coord].getBlockColor$() <> a_color Then Return 
		
		Container[x_coord, y_coord].setRegion(region_num)
		
		If x_coord > 0 Then tesRegion(a_color$, x_coord - 1, y_coord, region_num)
		If x_coord < 13 Then tesRegion(a_color$, x_coord + 1, y_coord, region_num)
		If y_coord > 0 Then tesRegion(a_color$, x_coord, y_coord - 1, region_num)
		If y_coord < 11 Then tesRegion(a_color$, x_coord, y_coord + 1, region_num)

		Return 
		
	End Method 



Here are the calls that I made to test the code:


Global blockContainer:BContainer = New BContainer

blockContainer.tesRegion(blockContainer.getContBlockColor(6,9), 6, 9, 1)



The program doesnt run until I comment out the following lines:

If x_coord > 0 Then tesRegion(a_color$, x_coord - 1, y_coord, region_num)

If y_coord > 0 Then tesRegion(a_color$, x_coord, y_coord - 1, region_num)


Anyone have any idea regarding what may be going wrong?