基本写好了有些按钮要点两三次才有反应 消去或者插旗帜 求解
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();
}
}
}
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();
}
}
}
因为windows在派发点击事件是,如果两次点击时间比较短就会吃掉两个点击事件,换成一个双击事件。
你的方法就现在鼠标右键按下事件里吧,不用点击事件吧。实例代码如下: class buttonAction extends MouseAdapter {
@Override
public void mousePressed(MouseEvent e) {
//把以前mouseClick代码移到这里
}
}
试用了一下。有些时候确实存在无法响应,要按两三次的情况。我确定我的输入速度没有达到双击的程度。
在未响应的几次中,可以看到console窗口没有输出。还有一次,点开无雷按钮,自动打开一部分按钮,其中有一个格子是空白的,但是它旁边的一个格子却是无论怎么点击,都保持未知的状态。
因为我也不是很熟悉eclipse,不知道如何在程序运行时看各数据当前的值。