我正在尝试制作一个程序来遍历 Sprite 图像,然后将其中的每个形状变成一个新图像。例如,如果我们选择马里奥,我希望帽子是一个图像,脸是另一个图像,依此类推。我已经让我的程序可以在小型 32x32 图像上运行,但如果我想在较大图像上运行它,则会导致堆栈溢出错误。如果我使用 C++,我会在每次递归调用后清除堆栈来解决此问题,但据我所知,Java 不允许您直接清除堆栈。我希望我的程序能够在 Windows、Linux 和 Mac 上运行,所以我认为 Java 将是最好的选择,所以我真的不想切换我正在使用的语言。有没有办法在 Java 中每次递归调用后删除存储在堆栈上的内容? 这是我的代码,以防万一出现错误。
private void makeShape(int x, int y)
{
if(x < 0 || y < 0 || y >= sprite.getHeight() || x >= sprite.getWidth())
{
return;
}
if(sample == colorData[y][x] && table[y][x])
{
tempBlankImage[y][x] = sample;
table[y][x] = false;
makeShape(x, y - 1);
makeShape(x, y + 1);
makeShape(x - 1, y);
makeShape(x + 1, y);
}
else
{
return;
}
}
x 和 y 点是通过 for 循环生成的,该循环遍历图像并检查点是否已添加到形状中,如果没有,则根据其周围的像素创建形状。
更新:
private int[][] makeShape(int sample, int x, int y)
{
int[][] tempBlankImage = blankImage();
Queue<Point> queue = new LinkedList<Point>();
queue.add(new Point(x,y));
while(!queue.isEmpty())
{
Point point = queue.remove();
if(sample == colorData[point.y][point.x] && table[point.y][point.x])
{
tempBlankImage[point.y][point.x] = sample;
table[point.y][point.x] = false;
if(point.y < sprite.getHeight() -1)
queue.add(new Point(point.x, point.y+1));
if(point.y > 0)
queue.add(new Point(point.x, point.y-1));
if(point.x < sprite.getWidth()-1)
queue.add(new Point(point.x+1, point.y));
if(point.x > 0)
queue.add(new Point(point.x-1, point.y));
}
}
queue = null;
return tempBlankImage;
}
堆栈溢出错误已停止,现在我出现内存不足:Java 堆空间,即使我将其增加到 2 GB。我将每个 int[][] 添加到 ArrayList 中,我猜这就是问题所在。我还能如何存储数据?
最佳答案
Java 以其自动定义良好且经过测试的内存管理系统而闻名 - 即使可能,自行管理内存通常也不是一个好主意(因为在某种程度上,它实际上是)。
如果算法执行时间能让你长出 mustache 并能够给你的孙子们讲关于它的故事,那么清理堆栈会给你带来什么?
不要使其递归 - 考虑算法的某种迭代形式。例如,您可以迭代所有图像的像素并将它们添加到适当的图像(由于其颜色),该图像将存储在某些 HashMap 中,如以下伪代码
HashMap<Color, Image> images= new HashMap<Color, Image>();
for(Pixel pixel : originImage)
Color color = pixel.getColor();
images.get(color).put(pixel)
不要为糟糕的代码浪费生命
关于Java:即使代码正确,递归也会导致堆栈溢出错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34325630/