这大概是个初级问题。但是,我已经阅读了《Java 绝对初学者编程》的第 12 章,并接触了一些示例代码。尝试编译此示例代码程序时出现编译器错误。我将所有相关程序都放在同一个包中,所以这不是问题。
错误发生在这一行:
minefield.addMineFieldListener(this);
它指出:
Exception in thread "main" java.lang.RuntimeException: Uncompilable source code
- Erroneous sym type: MineField.addMineFieldListener at MinePatrol.<init>
(MinePatrol.java:21)
我的主要问题是:为什么会发生这种情况?
非常感谢您在此问题上的时间和合作。
这是 MinePatrol.java 的代码:
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
import java.net.URL;
import java.net.MalformedURLException;
public class MinePatrol extends GUIFrame
implements MineFieldListener, ActionListener {
protected MineField minefield;
protected Button resetButton;
protected Label flagCountLabel;
public MinePatrol() {
super("MinePatrol");
minefield = new MineField(10, 10, 10);
minefield.addMineFieldListener(this);
add(minefield, BorderLayout.CENTER);
MediaTracker mt = new MediaTracker(this);
Image[] imgs = {
Toolkit.getDefaultToolkit().getImage("flag.gif"),
Toolkit.getDefaultToolkit().getImage("mine.gif"),
Toolkit.getDefaultToolkit().getImage("explode.gif") };
for (int i=0; i < imgs.length; i++) {
mt.addImage(imgs[i], i);
}
try {
mt.waitForAll();
} catch (InterruptedException e) {}
minefield.setImages(imgs[0], imgs[1], imgs[2]);
try {
minefield.setAudioClips(
Applet.newAudioClip(new URL("file:reveal.wav")),
Applet.newAudioClip(new URL("file:flag.wav")),
Applet.newAudioClip(new URL("file:unflag.wav")),
Applet.newAudioClip(new URL("file:explode.wav")));
} catch (MalformedURLException e) {}
flagCountLabel = new Label("Flags: 10", Label.CENTER);
add(flagCountLabel, BorderLayout.NORTH);
resetButton = new Button("Reset");
resetButton.addActionListener(this);
add(resetButton, BorderLayout.SOUTH);
pack();
setVisible(true);
}
public static void main(String args[]) {
new MinePatrol();
}
public void mineFieldSolved(MineFieldEvent e) {
flagCountLabel.setText("You Win!");
}
public void mineFieldRandomized(MineFieldEvent e) {
flagCountLabel.setText("Flags: " + minefield.getMineCount());
}
public void mineFieldDetonated(MineFieldEvent e) {
flagCountLabel.setText("You exploded into tiny bits... RIP");
}
public void mineFieldFlagCountChanged(MineFieldEvent e) {
flagCountLabel.setText("Flags: "
+ (minefield.getMineCount() - minefield.getFlagCount()));
}
public void actionPerformed(ActionEvent e) {
minefield.randomize();
}
}
这是 MineField.java 的代码
import java.awt.*;
import java.util.*;
import java.applet.AudioClip;
public class MineField extends Panel
implements MineCellListener {
protected int rows, cols, mines, flagged, revealed;
protected AudioClip revealClip, flagClip, unflagClip, explodeClip;
protected MineCell[][] cells;
//keeps track of MineCell indices
protected Hashtable pointIndex;
protected Vector listeners;
public MineField(int nRows, int nCols, int nMines) {
rows = nRows > 0 ? nRows : 1;
cols = nCols > 0 ? nCols : 1;
cells = new MineCell[rows][cols];
mines = nMines >= 0 && nMines < rows * cols ? nMines : 1;
pointIndex = new Hashtable(rows * cols);
setLayout(new GridLayout(rows, cols));
for (int r=0; r < cells.length; r++) {
for (int c=0; c < cells[r].length; c++) {
cells[r][c] = new MineCell();
cells[r][c].addMineCellListener(this);
//Points use (x, y) coordinates to x=c and y=r
pointIndex.put(cells[r][c], new Point(c, r));
cells[r][c].setSize(25, 25);
add(cells[r][c]);
}
}
listeners = new Vector();
randomizeField(false);
}
protected void randomizeField(boolean fireEvent) {
Random rand = new Random();
int index;
//initialize empty
for (int r=0; r < cells.length; r++) {
for (int c=0; c < cells[r].length; c++) {
cells[r][c].resetContents(MineCell.EMPTY);
}
}
//randomly place all mines
for (int m=0; m < mines; m++) {
do {
index = rand.nextInt(rows * cols);
}
while (cells[index / cols][index % cols].getContents() != MineCell.EMPTY);
cells[index / cols][index % cols].resetContents(MineCell.MINE);
}
setNumberClues();
flagged = revealed = 0;
//does not fire flagCountChanged, only mineFieldRandomized
if (fireEvent) (new EventThread(new MineFieldEvent(this,
MineFieldEvent.RANDOMIZED))).start();
}
public void randomize() {
randomField(true);
}
public int getFlagCount() {
return flagged;
}
public int getMineCount() {
return mines;
}
//counts and sets the number of mines surrounding each cell
protected void setNumberClues() {
int nMines;
for (int r=0; r < cells.length; r++) {
for (int c=0; c < cells[r].length; c++) {
if (cells[r][c].getContents() != MineCell.MINE) {
nMines = 0;
//count the number of mines surrounding this cell
for (int dr = r - 1; dr <= r + 1; dr++) {
//prevent ArrayIndexOutOfBoundsException
//continue puts control back to the beginning of the loop
if (dr < 0 || dr >= cells.length) continue;
for (int dc = c -1; dc <= c + 1; dc++) {
if (dc < 0 || dc >= cells[dr].length) continue;
if (cells[dr][dc].getContents() == MineCell.MINE) nMines++;
}
}
cells[r][c].resetContents(nMines);
}
}
}
}
public class MineFieldEvent extends java.util.EventObject {
protected int eventID;
//event id constants
public final static int SOLVED = 0,
RANDOMIZED = 1,
DETONATED = 2,
FLAG_COUNT_CHANGED = 3;
public MineFieldEvent(Object source, int id) {
super(source);
eventID = id;
}
public int getID() {
return eventID;
}
}
protected class EventThread extends Thread {
MineFieldEvent e;
EventThread(MineFieldEvent mfe) {
e = mfe;
}
public void addMineFieldListener(MineFieldListener mfl) {
listeners.addElement(mfl);
}
public void removeMineFieldListener(MineFieldListener mfl) {
listeners.removeElement(mfl);
}
public void run() {
switch(e.getID()) {
case MineFieldEvent.SOLVED:
for (int i=0; i < listeners.size(); i++) {
((MineFieldListener)listeners.elementAt(i)).mineFieldSolved(e);
}
break;
case MineFieldEvent.RANDOMIZED:
for (int i=0; i < listeners.size(); i++) {
((MineFieldListener)listeners.elementAt(i)).mineFieldRandomized(e);
}
break;
case MineFieldEvent.DETONATED:
for (int i=0; i < listeners.size(); i++) {
((MineFieldListener)listeners.elementAt(i)).mineFieldDetonated(e);
}
break;
case MineFieldEvent.FLAG_COUNT_CHANGED:
for (int i=0; i < listeners.size(); i++) {
((MineFieldListener)listeners.elementAt(i)).mineFieldFlagCountChanged(e);
}
break;
}
}
}
public void setImages(Image f, Image m, Image e) {
MineCell.setImages(f, m, e);
}
public void setAudioClips(AudioClip r, AudioClip f, AudioClip u,
AudioClip e) {
revealClip = r; flagClip = f; unflagClip = u; explodeClip = e;
}
/* Reveals areas mine-free minecells */
protected void showSafeArea(MineCell start) {
//get the point index for the starting cell
Point p = (Point)pointIndex.get(start);
for (int r = p.y - 1; r <= p.y + 1; r++) {
if (r < 0 || r >= cells.length) continue;
for (int c = p.x - 1; c <= p.x + 1; c++) {
if (c < 0 || c >= cells[r].length || !cells[r][c].isHidden())
continue;
if (cells[r][c].isFlagged()) {
flagged--;
(new EventThread(new MineFieldEvent(this,
MineFieldEvent.FLAG_COUNT_CHANGED))).start();
}
cells[r][c].setHidden(false);
revealed++;
if(cells[r][c].getContents() == MineCell.EMPTY)
showSafeArea(cells[r][c]);
}
}
}
protected void checkIfSolved() {
if (flagged + revealed == rows * cols) {
//solved if we get here.
revealAll();
(new EventThread(new MineFieldEvent(this,
MineFieldEvent.SOLVED))).start();
}
}
public void revealAll() {
for (int r=0; r < cells.length; r++) {
for (int c =0; c < cells.length; c++) {
cells[r][c].setHidden(false);
}
}
}
public void mineCellRevealed(MineCellEvent e) {
if (revealClip != null) revealClip.play();
revealed++;
if ((MineCell)e.getSource()).getContents() == MineCell.EMPTY)
showSafeArea((MineCell)e.getSource());
checkIfSolved();
}
public void mineCellDetonated(MineCellEvent e) {
//game over show all
if (explodeClip != null) explodeClip.play();
revealAll();
(new EventThread(new MineFieldEvent(this,
MineFieldEvent.DETONATED))).start();
}
public void mineCellFlagged(MineCellEvent e) {
if (flagged >= mines) {
((MineCell)e.getSource()).getHidden(true);
return;
}
if (flagClip != null) flagClip.play();
flagged++;
(new EventThread(new MineFieldEvent(this,
MineFieldEvent.FLAG_COUNT_CHANGED))).start();
checkIfSolved();
}
public void mineCellUnflagged(MineCellEvent e) {
if (unflagClip != null) unflagClip.play();
flagged--;
(new EventThread(new MineFieldEvent(this,
MineFieldEvent.FLAG_COUNT_CHANGED))).start();
}
}