Reputation: 2207
I'm trying to write an AI maze solver program. To do this, I will draw 2-color mazes in GIMP with red being walls and blue being background or floor. Then I will export from GIMP as a png and use ImageIO.read()
to get a BufferedImage
object of the maze. Finally, I will assign Rectangle
hitboxes to walls and store them in an ArrayList
so I can use .intersect()
to check for sprite contact with walls. I can work with it from here.
However, there is one thing I want to be able to do for my program that I don't know how to do: Once I have stored my image as a BufferedImage
, how can I detect the red parts (all the exact same RGB shade of red) and create matching Rectangle
s?
Notes:
Rectangle
objects which I create are just used as hitboxes so I can use .intersect()
, never drawn or anything like that.Rectangle
s that are created will be stored in an ArrayList
. What I want to be able to do: (green areas being where the java.awt.Rectangles
are created and stored into ArrayList
)
Upvotes: 2
Views: 1865
Reputation: 694
Last year, someone asked about a more general case for solving a maze. They had one additional complexity in that there were multiple paths, but the "correct" path through an intersection was straight.
The solution provided solves the maze by ray-casting. Starting at the beginning of a path, it projects lines down the path in all directions. Then it sorts the list and chooses the longest line and uses that to calculate the next starting point. Now, it repeats projecting lines in all directions except in the direction it came - the backtrack could be longer than the forward progress. That would just bounced the solution around in the longest leg of the maze.
If you are certain your angles are always 90 degrees, you could modify the code accordingly.
Upvotes: 1
Reputation: 5851
I will provide a quite naive way of solving the problem (not fully implemented, just so you get the idea)..
Have a list of all rectangles List<Rectangle> mazeRectangles
. All rectangles will be stored here.. And of course the image BufferedImage image;
Now we will iterate over all pictures until we find one with the right colour
Every time we found a rectangle, we will skip all x values for the width of the rectangle..
//iterate over every pixel..
for (int y = 0; y < image.getHeight(); y++) {
for (int x = 0; x < image.getWidth(); x++) {
//check if current pixel has maze colour
if(isMazeColour(image.getRGB(x, y))){
Rectangle rect = findRectangle(x, y);
x+=rect.width;
}
}
}
Your method for checking the colour:
public boolean isMazeColour(int colour){
// here you should actually check for a range of colours, since you can
// never expect to get a nicely encoded image..
return colour == Color.RED.getRGB();
}
The interesting part is the findRectangle
method..
We see if there is already a Rectangle
which contains our coordinates. If so return it, otherwise create a new Rectangle
, add it to the list and return it.
If we have to create a new Rectangle
, we will first check it's width. The annoying part about this is, that you'll still have to check every pixel for the rest of the rectangle, since you might have a configuration like that:
+++++++
+++++++
###
###
where #
and +
are separate boxes. So we first find the width:
public Rectangle findRectangle(int x, int y){
// this could be optimized. You could keep a separate collection where
// you remove rectangles from, once your cursor is below that rectangle
for(Rectangle rectangle : mazeRectangles){
if(!rectangle.contains(x, y)){
return rectangle;
}
}
//find the width of the `Rectangle`
int xD = 0;
while(x+xD < width && isMazeColour(image.getRGB(x+xD+1, y))){
xD++;
}
int yD = 0; //todo: find height of rect..
Rectangle toReturn = new Rectangle(x, y, xD, yD);
mazeRectangles.add(toReturn);
return toReturn;
}
I didn't implement the yD
part, since it's a bit messy and I am a little lazy, but you'd need to iterate over y and check each row (so two nested loops)
Note that this algorithm might result in overlapping Rectangle
s. if you don't want that, when finding xD
check for each pixel if it is already contained in a Rectangle
. Only expand xD
as long as you are not inside another Rectangle
.
Another thing: You might end up with strange artefacts at the border of your rectangles, due to the interpolation of colours between red and blue. Maybe you want to check for Rectangles being to small (like only 1 pixel wide) and get rid of them..
Upvotes: 2