views:

466

answers:

3
+9  A: 

A straightforward graphics algorithm called Flood fill can do this.

It can also be done in a simple multi-pass approach - the blockbuster board is so small that I don't think that visiting each cell many times will have any noticeable performance impact at all - so I'd advocate this approach be tried first:

For each player, loop through all the cells; if the cell is owned by the player, and is adjacent on one if it's six sides to a cell 'marked' by this fill routine, then the cell gets marked too. Loop again through all the cells, and again until no cells get marked to the current player. Here's some pseudo-code:

for player in players:
  # those on the starting edge that the player owns get 'marked'
  for cells in cells.start_edge(player):
    if cell.owner = player:
      cell.mark = player
  do:
    count = 0
    for cell in cells:
      if cell.mark == None && cell.owner == player:
        for adjacent in cell.neighbours:
          if adjacent.mark == player
            cell.owner = player
            count += 1
            break
  while count
  for cell in cells.stop_edge(player):
     if cell.mark == player
       player won!!

At this point, if any of the cells on the appropriate side of the board belong to the player, the player reached that side of the board.

Will
Flood fill looks nice. Still trying to get my head around the *"if the cell is empty, and is adjacent to a cell 'belonging' to the player, then the cell belongs to the player"* bit! Could you expand on that slightly?
h4xxr
@h4xxr: before start, white "owns" the half-filled hexes off the top of the board. Blue "owns" the hexes off the right. Then proceed as Will says - on each pass, a hex is assigned to a player if it is (a) of their colour, and (b) adjacent to a hex that player already owns. If a player owns a hex on the bottom row (white) or left column (blue), that player wins. With a bit of effort you could make the calculation iterative as each new tile is added, but that's almost certainly not worth it since a flood fill is instantaneous on a large image on modern hardware, never mind 20 cells...
Steve Jessop
Thanks onebyone, excellently summarised. And thanks will for expanding answer
h4xxr
+1  A: 

Your problem translates to whether two nodes are connected in a graph.

  • You can look at the board as a non-directed "graph". Nodes are the cells and they have edges if they are adjacent cells.
  • The sides are also nodes in the graph, and those have edges to the cells adjacent to them
  • Take the sub-graph of nodes you can use (including top and bottom if checking for that player)
  • Check if the top and bottom are connected using DFS
yairchu
It's not equivalent to Will's answer, flood fill is breadth first search.
starblue
@starblue: 10x. I fixed it
yairchu
+1  A: 
S.Lott
Thank you, very comprehensive answer. The situations where my old algorithm failed were when the "path" say from left to right went "back on itself", eg across the bottom, then back up diagonally left, then across the top to connect. If you're going from left to right (increasing x) will it still catch these situations?
h4xxr
That's the point. If x is always increasing, you can't double back. Your `enum_adjacent_horiz` method of a cell absolutely assure monotonic change in x. Similarly, `enum_adjacent_horiz` absolutely guarantees monotonic change in y.
S.Lott