So I have an assignment where I have to recreate a 3d chessboard that is a RxC grid of squares each being a different height. If the chessboard is water tight, and someone pours
Fun question, with many varied solutions. I've been thinking about it this afternoon and I would go for something like flood-fill with a priority queue (min-heap, perhaps). Let's call it the fence
.
You'll also want to keep track of which items have been visited. Mark all items as unvisited, initially.
Start off by adding all points around the perimeter of your grid to the fence
.
Now you loop like so:
Pop the front item from the fence
. You have selected one of the lowest points on the perimeter.
You now do a flood-fill from that point. You can do this recursively (depth-first), but I will discuss this using an unordered queue (breadth-first). Let's call this queue the flood
. You start by pushing the item onto flood
.
Flooding then goes like this: Loop until there are no items remaining in flood
...
flood
flood
.fence
. You'll want to have a way to tell whether the item is already in fence
- you don't want to add it again. Maybe you can extend your 'visited' flags to cope with this.And that's it. Admittedly it was just a thought experiment while I lay around feeling hungover and seedy, but I reckon it's good.
As you requested... Some pseudocode.
Initial setup:
## Clear flags. Note I've added a 'flooding' flag
for each item in map
item.visited <- false # true means item has had its water depth added
item.fenced <- false # true means item is in the fence queue
item.flooding <- false # true means item is in the flooding queue
end
## Set up perimeter
for each item on edge of map (top, left, right, bottom)
push item onto fence
end
waterlevel <- 0
total <- 0
Now the main chunk of the algorithm
while fence has items
item <- pop item from fence
if item.visited = true then loop again
## Update water level
if item.height > waterlevel then waterlevel = item.height
## Flood-fill item using current water level
push item onto flood
item.flooding <- true
while flood has items
item <- pop item from flood
depth <- waterlevel - item.height
if depth >= 0 then
# Item is at or below water level. Add its depth to total.
total <- total + depth
item.visited <- true
# Consider all immediate neighbours of item.
for each neighbour of item
if neighbour.visited = false then
if neighbour.flooding = false then
push neighbour onto flood
neighbour.flooding <- true
end
end
end
else
# Item is above water
item.flooding <- false
if item.fenced = false then
push item onto fence
item.fenced <- true
end
end
end
end