基本写好了有些按钮要点两三次才有反应  消去或者插旗帜 求解
import java.awt.*;
import java.awt.event.*;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;import javax.swing.*;/*
 * 扫雷 边框 == -100 无雷(未挖)== -1 无雷(已挖)== -2 地雷 == 1
 */public class Test
{
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run() 
{
CalculatorFrame frame = new CalculatorFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}class CalculatorFrame extends JFrame
{
public CalculatorFrame()
{
setTitle("扫雷");
setSize(450, 480); CalculatorPanel panel = new CalculatorPanel();
add(panel);
}
}class CalculatorPanel extends JPanel
{
private JPanel confirmPanel;
private JButton display;
private JButton quit;
private JPanel panel;
private buttonExp [][] g;
private List<buttonExp> listGame = new LinkedList<buttonExp>();//这个用来保存已经遍历过的点
private List<buttonExp> listLei = new LinkedList<buttonExp>();//用来存已经存在的地雷 保存 啊 副本啊 标记用的
private int digRightCount;

private ImageIcon bombIcon;
private ImageIcon flagIcon;

public CalculatorPanel()
{

//导入地雷图标
java.net.URL imgURL = Test.class.getResource("/bomb.gif"); 
bombIcon = new ImageIcon(imgURL); 
imgURL = Test.class.getResource("/flag.gif"); 
flagIcon = new ImageIcon(imgURL); 

setLayout(new BorderLayout());

//添加一个panel 上面有重新开始按钮
confirmPanel = new JPanel();

display = new JButton("Restart");
choiceAction listenerC = new choiceAction(-2, -2);
display.addActionListener(listenerC);
confirmPanel.add(display);

quit = new JButton("  Quit ");
choiceAction listenerQ = new choiceAction(-1, -1);
quit.addActionListener(listenerQ);
confirmPanel.add(quit);

add(confirmPanel, BorderLayout.NORTH);


//12*12的方格 全部初始化为0 添加到panel
panel = new JPanel();
panel.setLayout(new GridLayout(10, 10));

g = new buttonExp[12][12];

//全部初始化很小的数字 包括 棋盘和周边
for (int i = 0; i < 12; i++)
{
for (int j = 0; j < 12; j++)
{
buttonExp button = new buttonExp(-100, i, j);//此处创建实例  可默认参数节俭空间
g[i][j] = button;
}
}

//边框以内初始化为-1 为撒地雷做准备
for (int i = 1; i < 11; i++)
{
for (int j = 1; j < 11; j++)
{
buttonExp button = new buttonExp(-1, i, j);
g[i][j] = button;
buttonAction listener = new buttonAction();
g[i][j].addMouseListener(listener);
panel.add(button);
}
}
add(panel,BorderLayout.CENTER);

//开始布置地雷了
Random ran=new Random();
for (int i = 0; i < 20; i++)
{
int x = ran.nextInt(10) + 1;//ran范围 0-(n-1)
int y = ran.nextInt(10) + 1;
//若已包含这个点
if (listLei.contains(g[x][y]))
{
i--;
continue;
}
g[x][y].flag = 1;
listLei.add(g[x][y]);
}
//showBomb();
}

class buttonAction extends MouseAdapter
{
public void mouseClicked(MouseEvent e)   

buttonExp button=(buttonExp)e.getSource(); //获取触发事件来源

//左键
if(!SwingUtilities.isRightMouseButton(e))
{
//已消去 不做处理
if (button.flag == -2)
return;

//已经标记的雷 不做处理
if (button.dig == 1)
return;

//未标记 未消去 该点有地雷
if (button.flag == 1)
{
showBomb();
for (int i = 1; i < 11; i++)
{
for (int j = 1; j < 11; j++)
{
g[i][j].setEnabled(false);
}
}
JOptionPane.showMessageDialog(null, "you lost");
}

//未标记 未消去 没地雷
else
{
int x = button.line;
int y = button.row;
showSpace(x, y);
repaint();
}

return; 
}

     //右键
else
{
//已消去 不做处理
if (button.flag == -2)
return;

//已经标记过  拔掉标记 正确数减1
if (button.dig == 1)
{
button.dig = 0;
if (listLei.contains(button))
digRightCount--;
button.setIcon(null);
System.out.print(digRightCount);/////////////////////////////////
return;
}

//标记
else
{
button.dig = 1;
if (listLei.contains(button))
digRightCount++;
button.setIcon(flagIcon);
System.out.print(digRightCount);/////////////////////////////////

//若全部点亮 获胜!
if (digRightCount == 20)
JOptionPane.showMessageDialog(null, "you win");

}

}
    

}
//轻度包装的Button
class buttonExp extends JButton
{
public int flag;//边框 == -100 无雷(未挖)== -1 无雷(已挖)== -2地雷 == 1
public int line;//原属行
public int row;//原数列
public int dig;//是否标雷  标记雷 1 未标记 0  

public buttonExp(int x, int l, int r)
{
super();
flag = x;
line = l;
row = r;
dig = 0;
}
}

//处理那两个按钮重新开始和退出
class choiceAction implements ActionListener 
{
public int x;
public int y;

public choiceAction(int xL,int yL)
{
x = xL;
y = yL;
}

public void actionPerformed(ActionEvent event)
{
if (x == y && x == -1)
System.exit(0);
if (x == y && x == -2)
{

//list清空 dig清空
listGame.clear();
listLei.clear();
digRightCount = 0;
//边框以内初始化为-1 为撒地雷做准备
for (int i = 1; i < 11; i++)
{
for (int j = 1; j < 11; j++)
{
g[i][j].flag = -1;
g[i][j].setEnabled(true);
g[i][j].setIcon(null);
g[i][j].setText(null);
}
}

//又开始布置地雷了
Random ran=new Random();
for (int i = 0; i < 20; i++)
{
int x = ran.nextInt(10) + 1;//ran范围 0-(n-1)
int y = ran.nextInt(10) + 1;
//若已包含这个点
if (listLei.contains(g[x][y]))
{
i--;
continue;
}
g[x][y].flag = 1;
listLei.add(g[x][y]);
//showBomb();
}
repaint();
}
}
}

public int count(int x, int y)
{
int count = 0;
if (g[x - 1][y].flag == 1)
count++;
if (g[x + 1][y].flag == 1)
count++;
if (g[x][y - 1].flag == 1)
count++;
if (g[x][y + 1].flag == 1)
count++;

if (g[x - 1][y - 1].flag == 1)
count++;
if (g[x + 1][y - 1].flag == 1)
count++;
if (g[x - 1][y + 1].flag == 1)
count++;
if (g[x + 1][y + 1].flag == 1)
count++;
return count;
}

public void showSpace(int x, int y) 
{
//点跑到边界上了 不显示  返回
if (x < 1 || x > 10 || y < 1 || y > 10)
{
return;
}

//如果你已经标记出来这个了
if (g[x][y].dig == 1)
{
g[x][y].setEnabled(true);
return;
}


//既然自己不是雷 先把自己设置成false
g[x][y].setEnabled(false);
System.out.println(x + "   " + y);

//这个点的四周检查过了
listGame.add(g[x][y]);

//边上有雷终止 显示雷数 返回
if (count(x,y) != 0)
{
g[x][y].setText(Integer.toString(count(x, y), 10));
return;
}


//这下头都是四周没有地雷的 

//先把四周的点设置成已经被扫的雷
g[x][y - 1].flag = -2;
g[x][y + 1].flag = -2;
g[x - 1][y].flag = -2;
g[x + 1][y].flag = -2;

g[x + 1][y + 1].flag = -2;
g[x + 1][y - 1].flag = -2;
g[x - 1][y + 1].flag = -2;
g[x - 1][y - 1].flag = -2;

//再把所有点设置成false
g[x][y - 1].setEnabled(false);
g[x][y + 1].setEnabled(false);
g[x - 1][y].setEnabled(false);
g[x + 1][y].setEnabled(false);

g[x + 1][y + 1].setEnabled(false);
g[x + 1][y - 1].setEnabled(false);
g[x - 1][y + 1].setEnabled(false);
g[x - 1][y - 1].setEnabled(false);

//对下一个点进行显示判断
if (listGame.contains(g[x][y + 1]) == false)
showSpace(x, y + 1);
if (listGame.contains(g[x][y - 1]) == false)
showSpace(x, y - 1);
if (listGame.contains(g[x + 1][y]) == false)
showSpace(x + 1, y);
if (listGame.contains(g[x - 1][y]) == false)
showSpace(x - 1, y); if (listGame.contains(g[x + 1][y + 1]) == false)
showSpace(x + 1, y + 1);
if (listGame.contains(g[x + 1][y - 1]) == false)
showSpace(x + 1, y - 1);
if (listGame.contains(g[x - 1][y + 1]) == false)
showSpace(x - 1, y + 1);
if (listGame.contains(g[x - 1][y - 1]) == false)
showSpace(x - 1, y - 1);

}

public void showBomb()
{

for (int i = 1; i < 11; i++)
{
for (int j = 1; j < 11; j++)
{
if (1 == g[i][j].flag)
{
g[i][j].setIcon(bombIcon);
}
}
System.out.println();
}
}
}

解决方案 »

  1.   

    稍微看了一下。基本上OK,至于你说的那种情况,应该是连续快速点击鼠标右键时可能点不上,这个是正常的
    因为windows在派发点击事件是,如果两次点击时间比较短就会吃掉两个点击事件,换成一个双击事件。
    你的方法就现在鼠标右键按下事件里吧,不用点击事件吧。实例代码如下:    class buttonAction extends MouseAdapter {
                
            
            @Override
            public void mousePressed(MouseEvent e) {
                //把以前mouseClick代码移到这里
            }
            
        }
      

  2.   

    看了半天,没怎么看懂。
    试用了一下。有些时候确实存在无法响应,要按两三次的情况。我确定我的输入速度没有达到双击的程度。
    在未响应的几次中,可以看到console窗口没有输出。还有一次,点开无雷按钮,自动打开一部分按钮,其中有一个格子是空白的,但是它旁边的一个格子却是无论怎么点击,都保持未知的状态。
    因为我也不是很熟悉eclipse,不知道如何在程序运行时看各数据当前的值。