我正在制作一个扫雷克隆,目的是教我自己摇摆和更一般地理解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类构建我的棋盘,对它的调用返回我已经制作的炸弹阵列。它是一个Bomb对象数组,长度为150个元素。
非常感谢任何关于如何阻止这种溢出的想法,谢谢。
答案 0 :(得分:0)
如果我试图调试这个,我会做一些打印到控制台的实验来弄清楚我的逻辑错误在哪里。我做这样的事情:
public void check() {
System.out.println("Checking location index = " + index);
// Some code omitted
if(imageNumber == 0) {
System.out.println("Location number " + index + " has no bombs surrounding it.");
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) {
// Remaining Code omitted
}
正如其他一些想法一样,如果要使用二维数组,代码可能更容易阅读。然后你可以直接索引到x,y位置而不是做巧妙的数组切片。
最后,您可以考虑编写一些探索问题的单元测试。我从没有炸弹的1对1网格开始,看看&#39;检查&#39;方法呢。这可能会使问题变得清晰。
希望这有帮助!