I have some function, and this function's purpose is to take a grid, and search, in a flood-fill pattern, until it finds a size. Once that size is found, it should return the {x,y} object. The main issue that I'm having is that I don't know how to get it to properly return without crashing or going into an infinite loop.
function floodFillSearch(room: Room, startPosition: RoomPosition, structure: StampType, plannedPositions: RoomPosition[]): RoomPosition | undefined {
Logger.log(`Start Position: ${startPosition.x}, ${startPosition.y}`, LogLevel.DEBUG)
let x = startPosition.x
let y = startPosition.y
if (x > 49 || y > 49 || x < 0 || y < 0) { return }
if (x + 1 > 49 || y + 1 > 49 || x - 1 < 0 || y - 1 < 0) { return }
Logger.log(`Searching for ${structure} at ${x},${y}`, LogLevel.DEBUG)
if (doesStampFitAtPosition(startPosition.x, startPosition.y, room, structure, plannedPositions)) {
return new RoomPosition(startPosition.x, startPosition.y, startPosition.roomName)
}
let rightResult = floodFillSearch(room, new RoomPosition(startPosition.x + 1, startPosition.y, room.name), structure, plannedPositions, visited)
let leftResult = floodFillSearch(room, new RoomPosition(startPosition.x - 1, startPosition.y, room.name), structure, plannedPositions, visited)
let topResult = floodFillSearch(room, new RoomPosition(startPosition.x, startPosition.y + 1, room.name), structure, plannedPositions, visited)
let bottomResult = floodFillSearch(room, new RoomPosition(startPosition.x, startPosition.y - 1, room.name), structure, plannedPositions, visited)
if (rightResult) { return rightResult }
if (leftResult) { return leftResult }
if (topResult) { return topResult }
if (bottomResult) { return bottomResult }
return
}
Some notes, the bounds of the array are 0,0 -> 49,49. And the doesStampFitAtPosition() function checks the adjacent n size spaces and if it doesn't contain a value that's already predetermined, then it returns true, otherwise false. For example, a global color might exist, it would check if that global color, with the size of 5x5 grid, given the starting position, exists.
Notes
- The
RoomPositioncontains properties forxandyultimately, I'm just trying to get thexandyposition that is first found.
Update
- I have been told I'm looking for a breadth-first search.
To avoid that your traversal runs in circles, you need to somehow mark your cells as "visited". There are several ways to do that, for instance with a Set where you add a unique reference to a cell.
In the initial call you would not pass the
visitedargument, so it gets initialised as an empty Set.The above is a depth-first search, and is rather memory efficient for finding a target. But if you are interested in the closest hit, then a breadth-first search is often the chosen method -- this will search all cells at a short distance, then all cells that are one step further from the source, ...etc.
The code could look like this:
This uses a specific behaviour of Set: when
.addis called with a value that is already in the set, the set doesn't change, but if it is not in the set yet, it gets added in such a way that thefor..ofloop is guaranteed to visit it in a next iteration.