【发布时间】:2014-05-23 14:40:53
【问题描述】:
我正在制作一个 Minesweeper 克隆,目的是自学 Swing 并更全面地了解 Java。我几乎完全完成了它,除了我无法让级联方法正常工作。
我知道我的错误在于我的递归,但我似乎不明白如何停止它。我能得到的最好方法是在 1 次迭代后停止该方法,但它确实需要全面级联。
这是堆栈跟踪:
Exception in thread "AWT-EventQueue-0" java.lang.StackOverflowError
at bombSweeper.BombSweeper.getField(BombSweeper.java:1168)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
at bombSweeper.Bomb.check(Bomb.java:316)
行号总是指下面代码中的递归调用,它会根据按钮在我的雷区中的位置而变化。
package bombSweeper;
import java.awt.Insets;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
public class Bomb extends JButton implements MouseListener {
int imageNumber, index, defusedCheck;
boolean isBomb, isChecked, isFlagged;
private ImageIcon bomb = new ImageIcon("./imgs/bomb.png"),
flag = new ImageIcon("./imgs/flag.png"),
one = new ImageIcon("./imgs/1.png"),
two = new ImageIcon("./imgs/2.png"),
three = new ImageIcon("./imgs/3.png"),
four = new ImageIcon("./imgs/4.png"),
five = new ImageIcon("./imgs/5.png"),
six = new ImageIcon("./imgs/6.png"),
seven = new ImageIcon("./imgs/7.png"),
eight = new ImageIcon("./imgs/8.png");
public Bomb(int index) {
isBomb = false;
isChecked = false;
isFlagged = false;
imageNumber = 0;
this.index = index;
addMouseListener(this);
setMargin(new Insets(0, 0, 0, 0));
setFocusPainted(false);
}
public boolean isBomb() {
return isBomb;
}
public void setBomb() {
isBomb = true;
imageNumber = 9;
}
public void setCount(int adjBombs) {
imageNumber = adjBombs;
}
public void flag() {
if(!isFlagged) {
this.setIcon(flag);
} else {
this.setIcon(null);
}
isFlagged ^= true;
}
public void check() {
if(isFlagged || isChecked) {
return;
}
if(isBomb) {
detonate();
return;
}
if(imageNumber != 0) {
if(imageNumber == 1) {
this.setIcon(one);
} else if(imageNumber == 2) {
this.setIcon(two);
} else if(imageNumber == 3) {
this.setIcon(three);
} else if(imageNumber == 4) {
this.setIcon(four);
} else if(imageNumber == 5) {
this.setIcon(five);
} else if(imageNumber == 6) {
this.setIcon(six);
} else if(imageNumber == 7) {
this.setIcon(seven);
} else if(imageNumber == 8) {
this.setIcon(eight);
}
isChecked = true;
}
if(imageNumber == 0) {
this.setEnabled(false);
if(index == 0) {
check(BombSweeper.getField()[index + 1]);
check(BombSweeper.getField()[index + 10]);
check(BombSweeper.getField()[index + 11]);
} else if(index > 0 && index < 9) {
check(BombSweeper.getField()[index - 1]);
check(BombSweeper.getField()[index + 1]);
check(BombSweeper.getField()[index + 9]);
check(BombSweeper.getField()[index + 10]);
check(BombSweeper.getField()[index + 11]);
} else if(index == 9) {
check(BombSweeper.getField()[index - 1]);
check(BombSweeper.getField()[index + 9]);
check(BombSweeper.getField()[index + 10]);
} else if(index % 10 == 0 && index != 140) {
check(BombSweeper.getField()[index - 10]);
check(BombSweeper.getField()[index - 9]);
check(BombSweeper.getField()[index + 1]);
check(BombSweeper.getField()[index + 10]);
check(BombSweeper.getField()[index + 11]);
} else if((index - 9) % 10 == 0 && index != 149) {
check(BombSweeper.getField()[index - 11]);
check(BombSweeper.getField()[index - 10]);
check(BombSweeper.getField()[index - 1]);
check(BombSweeper.getField()[index + 9]);
check(BombSweeper.getField()[index + 10]);
} else if(index == 140) {
check(BombSweeper.getField()[index - 10]);
check(BombSweeper.getField()[index - 9]);
check(BombSweeper.getField()[index + 1]);
} else if (index > 140 && index < 149) {
check(BombSweeper.getField()[index - 11]);
check(BombSweeper.getField()[index - 10]);
check(BombSweeper.getField()[index - 9]);
check(BombSweeper.getField()[index - 1]);
check(BombSweeper.getField()[index + 1]);
} else if(index == 149) {
check(BombSweeper.getField()[index - 11]);
check(BombSweeper.getField()[index - 10]);
check(BombSweeper.getField()[index - 1]);
} else {
check(BombSweeper.getField()[index - 11]);
check(BombSweeper.getField()[index - 10]);
check(BombSweeper.getField()[index - 9]);
check(BombSweeper.getField()[index - 1]);
check(BombSweeper.getField()[index + 1]);
check(BombSweeper.getField()[index + 9]);
check(BombSweeper.getField()[index + 10]);
check(BombSweeper.getField()[index + 11]);
}
}
}
public void check(Bomb bobomb) {
if(isFlagged || isChecked) {
return;
}
if(imageNumber != 0) {
if(imageNumber == 1) {
this.setIcon(one);
} else if(imageNumber == 2) {
this.setIcon(two);
} else if(imageNumber == 3) {
this.setIcon(three);
} else if(imageNumber == 4) {
this.setIcon(four);
} else if(imageNumber == 5) {
this.setIcon(five);
} else if(imageNumber == 6) {
this.setIcon(six);
} else if(imageNumber == 7) {
this.setIcon(seven);
} else if(imageNumber == 8) {
this.setIcon(eight);
}
isChecked = true;
} else if(imageNumber == 0) {
if(index == 0) {
check(BombSweeper.getField()[index + 1]);
check(BombSweeper.getField()[index + 10]);
check(BombSweeper.getField()[index + 11]);
} else if(index > 0 && index < 9) {
check(BombSweeper.getField()[index - 1]);
check(BombSweeper.getField()[index + 1]);
check(BombSweeper.getField()[index + 9]);
check(BombSweeper.getField()[index + 10]);
check(BombSweeper.getField()[index + 11]);
} else if(index == 9) {
check(BombSweeper.getField()[index - 1]);
check(BombSweeper.getField()[index + 9]);
check(BombSweeper.getField()[index + 10]);
} else if(index % 10 == 0 && index != 140) {
check(BombSweeper.getField()[index - 10]);
check(BombSweeper.getField()[index - 9]);
check(BombSweeper.getField()[index + 1]);
check(BombSweeper.getField()[index + 10]);
check(BombSweeper.getField()[index + 11]);
} else if((index - 9) % 10 == 0 && index != 149) {
check(BombSweeper.getField()[index - 11]);
check(BombSweeper.getField()[index - 10]);
check(BombSweeper.getField()[index - 1]);
check(BombSweeper.getField()[index + 9]);
check(BombSweeper.getField()[index + 10]);
} else if(index == 140) {
check(BombSweeper.getField()[index - 10]);
check(BombSweeper.getField()[index - 9]);
check(BombSweeper.getField()[index + 1]);
} else if (index > 140 && index < 149) {
check(BombSweeper.getField()[index - 11]);
check(BombSweeper.getField()[index - 10]);
check(BombSweeper.getField()[index - 9]);
check(BombSweeper.getField()[index - 1]);
check(BombSweeper.getField()[index + 1]);
} else if(index == 149) {
check(BombSweeper.getField()[index - 11]);
check(BombSweeper.getField()[index - 10]);
check(BombSweeper.getField()[index - 1]);
} else {
check(BombSweeper.getField()[index - 11]);
check(BombSweeper.getField()[index - 10]);
check(BombSweeper.getField()[index - 9]);
check(BombSweeper.getField()[index - 1]);
check(BombSweeper.getField()[index + 1]);
check(BombSweeper.getField()[index + 9]);
check(BombSweeper.getField()[index + 10]);
check(BombSweeper.getField()[index + 11]);
}
}
}
public void detonate() {
for(int i = 0; i < 150; i++) {
BombSweeper.getField()[i].isChecked = true;
if(BombSweeper.getField()[i].isBomb) {
BombSweeper.getField()[i].setIcon(bomb);
}
}
}
@Override
public void mousePressed(MouseEvent e) {
if(!isChecked) {
if(e.getButton() == 1) {
check();
}
if(e.getButton() == 3) {
flag();
}
}
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent arg0) {
}
@Override
public void mouseClicked(MouseEvent arg0) {}
@Override
public void mouseReleased(MouseEvent arg0) {}
}
BombSweeper 类构建了我的棋盘,调用它会返回我制作的炸弹数组。它是一个 150 个元素长的 Bomb 对象数组。
任何关于如何阻止这种溢出的想法将不胜感激,谢谢。
【问题讨论】:
-
您必须在进入递归之前在字段上设置“已处理”指示符。目前您不在
imageNumber == 0时设置isChecked标志。但是您将enabled设置为false,因此您可以将方法的第一行更改为if(isFlagged || isChecked || !isEnabled()) return; -
感谢您的建议。我只是去做了那个改变,结果就像我以前一样。它停止了无限递归,但它只检查最多 1 个单元格。恐怕我可能不得不再次完全修改我的检查方法。大声笑,我希望第七次是魅力。
标签: java swing recursion stack-overflow