我正在尝试编写AI迷宫解算器程序。为此,我将在GIMP中绘制双色迷宫,其中红色为墙壁,蓝色为背景或地板。然后我将从GIMP导出为png并使用ImageIO.read()
获取迷宫的BufferedImage
对象。最后,我会将Rectangle
点击框分配到墙上并将其存储在ArrayList
中,以便我可以使用.intersect()
检查精灵与墙壁的接触情况。我可以从这里开始使用它。
但是,我希望能为我的程序做一件我不知道该怎么做的事情:一旦我将图像存储为BufferedImage
,我该如何检测红色部分(所有完全相同的RGB红色阴影)并创建匹配的Rectangle
s?
注意:
Rectangle
个对象仅用作命中框,因此我可以使用.intersect()
,从不绘制或类似的东西。Rectangle
将存储在ArrayList
中。 我希望能够做到的事情:(绿色区域是创建java.awt.Rectangles
并存储到ArrayList
中)
答案 0 :(得分:2)
我将提供一种非常天真的方法来解决问题(没有完全实现,只是让你明白了)..
列出所有矩形List<Rectangle> mazeRectangles
。所有矩形都将存储在这里..当然还有图像BufferedImage image;
现在我们将迭代所有图片,直到找到一个颜色正确的图片
每次我们找到一个矩形时,我们都会跳过矩形宽度的所有x值。
//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;
}
}
}
检查颜色的方法:
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();
}
有趣的部分是findRectangle
方法..
我们看看是否已经有Rectangle
包含我们的坐标。如果是,则返回它,否则创建一个新的Rectangle
,将其添加到列表并返回它。
如果我们必须创建一个新的Rectangle
,我们将首先检查它的宽度。令人讨厌的部分是,你仍然需要检查矩形其余部分的每个像素,因为你可能有这样的配置:
+++++++
+++++++
###
###
其中#
和+
是单独的框。所以我们首先找到宽度:
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;
}
我没有实现yD
部分,因为它有点乱,我有点懒,但你需要迭代y并检查每一行(所以两个嵌套循环)
请注意,此算法可能会导致Rectangle
重叠。如果您不希望这样,那么当找到xD
时,检查每个像素是否已包含在Rectangle
中。只要您不在另一个xD
内,就展开Rectangle
。
另一件事:由于红色和蓝色之间的颜色插值,你可能会在矩形的边界处出现奇怪的人工制品。也许你想检查矩形是否小(只有1像素宽)并摆脱它们。
答案 1 :(得分:1)
去年,有人询问了一个解决迷宫的更一般案例。他们有一个额外的复杂性,因为有多条路径,但&#34;正确&#34;通过十字路口的道路是直的。
所提供的解决方案通过光线投射解决了迷宫问题。从路径的开头开始,它沿着路径沿着所有方向投射线。然后它对列表进行排序并选择最长的行并使用它来计算下一个起始点。现在,它在所有方向上重复投射线除了之外的方向 - 回溯可能比向前进展更长。这只会在迷宫中最长的一条腿上弹出解决方案。
如果您确定角度始终为90度,则可以相应地修改代码。