Created
February 13, 2017 01:06
-
-
Save codekitchen/b0ce51a6eb3245e0d21e78933b2d3334 to your computer and use it in GitHub Desktop.
optimized flood fill algorithm for random puzzle generation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class PuzzleGenerator { | |
// ... other stuff ... | |
class FloodFillRange { | |
public int startX, endX, Y; | |
} | |
// Does a flood fill of the board starting at an arbitrary floor tile, | |
// and then verifies that the whole board was filled. | |
// If not, then there's floor that isn't reachable from some other floor. | |
bool Reachable() { | |
bool[,] visited = new bool[size.y, size.x]; | |
var q = new Queue<FloodFillRange>(); | |
// Fill one horizontal line, starting at the given point, | |
// and stopping when we hit a wall (or the edge of the board). | |
System.Action<int, int> lineFill = (int x, int y) => { | |
int lx, rx; | |
// go left until stopped, marking as we go | |
for (lx = x; lx >= 0; --lx) { | |
if (board[y, lx].tile != BLANK) | |
break; | |
visited[y, lx] = true; | |
} | |
// go right until stopped, marking as we go | |
for (rx = x + 1; rx < size.x; ++rx) { | |
if (board[y, rx].tile != BLANK) | |
break; | |
visited[y, rx] = true; | |
} | |
// contract 1 from each side to get back to the last tile we visited | |
q.Enqueue(new FloodFillRange { startX = lx + 1, endX = rx - 1, Y = y }); | |
}; | |
// find start pos | |
foreach (var pos in eachPosition()) { | |
if (board[pos.y, pos.x].tile == BLANK) { | |
// prime the queue starting at this position | |
lineFill(pos.x, pos.y); | |
break; | |
} | |
} | |
while (q.Count > 0) { | |
var range = q.Dequeue(); | |
for (int x = range.startX; x <= range.endX; ++x) { | |
int y = range.Y - 1; | |
if (y >= 0 && !visited[y, x] && board[y, x].tile == BLANK) | |
lineFill(x, y); | |
y = range.Y + 1; | |
if (y < size.y && !visited[y, x] && board[y, x].tile == BLANK) | |
lineFill(x, y); | |
} | |
} | |
// look for any still-blank squares | |
foreach (var pos in eachPosition()) { | |
if (board[pos.y, pos.x].tile == BLANK && !visited[pos.y, pos.x]) | |
return false; | |
} | |
return true; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment