学了两周的java,想着做点东西玩玩,萌生了写一个扫雷的想法,这个想法其实在学c语言时就有了,当时并不知道c也有图形库,在后来就搁置了,最近看了大概两周的java,刚好看完 java Swing图形界面,老师说应该做个小项目检验一下学习成果,想着还是扫雷吧。
写了有两天,头一天把基本的的东西做出来了,第二天主要进行了一些优化,最后鼠标右键标记雷的功能没加上,原因是在把按钮置为不可用时,居然还是可以双击点击???但在换一个程序中试验时却没有这个现象,经过多方查找还是没有解决,只好作罢,最后,附上源码(如有需要图片等资源,请自行下载文章末尾打包文件,可以直接运行(无Java环境亦可运行))。
注:如果你使用了我的代码,请随手点个赞。
package testone;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.InputEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.Arrays;
import javax.swing.Box;
import javax.swing.ButtonGroup;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.Timer;
public class SaoLei {
public static void main(String[] args) {
// JFrame.setDefaultLookAndFeelDecorated(true); //使窗口美观,创建窗口前使用
GuiSl test = new GuiSl("扫雷",600,300,240,320);
//窗口改变大小,图片也随之改变大小以适应窗口
test.addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
int w = test.ls.getWidth()/test.x;
int h = test.ls.getHeight()/test.y;
for(int b0 = 0;b0 < test.x;b0++) {
for(int b1 = 0;b1 < test.y;b1++) {
// test.biu[b0][b1].setDisabledIcon(setImageSize0("Image\\SaoLei\\mine.jpg",w,h));
if(!test.book[b0][b1]) continue;
ImageIcon im = (ImageIcon)test.biu[b0][b1].getIcon();
im.setImage(im.getImage().getScaledInstance(w,h,Image.SCALE_DEFAULT));
test.biu[b0][b1].setIcon((Icon)im);
}
}
}
});
}
}
/**
* 建立基本窗口
* @author ds_surk
*
*/
class GuiSl extends JFrame {
JMenuBar bar;
JMenu m1,m2;
JMenuItem i1,i2,i3,i4,i5;
JButton [][] biu; //扫雷界面按钮
JPanel ls; //容器
int [] mines; //设置mine数量
static int x = 9,y = 9,num = 10,sum=0; //grid行列,雷的数量,已扫的雷
boolean [][] book; //标记数组
Timer time;
JLabel tu; //秒表图
JLabel tm0 = new JLabel(); //计时
JTextField re = new JTextField(); //留下姓名文本框
int max1 = 999999; //最大的耗时
GuiSl(){}
GuiSl(String s,int x,int y,int width,int height){
setBounds(x, y, width, height); //设置大小
setLocationRelativeTo(null); //设置为放在屏幕中央
setVisible(true); //设置窗口可见
// pack(); //设置调整窗口大小以适应组件
setDefaultCloseOperation(3); //设置关闭方式
inits(s);
setVisible(true);
}
/**
* 获取窗口本身
* @return
*/
GuiSl getck() {
return this;
}
void inits(String s){
init0(s);
init1();
}
void init0(String s) {
setTitle(s);
setIconImage(getToolkit().getImage("Image\\SaoLei\\0.jpg")); //设置图标
bar = new JMenuBar();
m1 = new JMenu("游戏");
m2 = new JMenu("帮助");
i1 = new JMenuItem("新游戏");
i2 = new JMenuItem("设置");
i3 = new JMenuItem("排名");
i4 = new JMenuItem("help");
i5 = new JMenuItem("关于");
i1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ini();
}
}); //设置监视器
i1.setAccelerator(KeyStroke.getKeyStroke("F2")); //设置快捷键
i2.addActionListener(new Set0());
i2.setAccelerator(KeyStroke.getKeyStroke("F4"));
i3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
paiHang();
}
});
i3.setAccelerator(KeyStroke.getKeyStroke("F6"));
i4.addActionListener(new Help());
i5.addActionListener(new GYu());
m1.add(i1);
m1.addSeparator(); //添加菜单项分界线
m1.add(i2);
m1.addSeparator();
m1.add(i3);
m2.add(i4);
m2.addSeparator();
m2.add(i5);
bar.add(m1);
bar.add(m2);
setJMenuBar(bar);
}
void init1() {
setGrid(x,y); //设置网格
setRand(num); //设置雷的位置
tm0.setText("0");
Box tim = Box.createHorizontalBox();
tu = new JLabel(":");
tu.setIcon(new ImageIcon("Image\\SaoLei\\time.jpg"));
ls = new JPanel();
ls.setLayout(new GridLayout(x,y));
biu = new JButton[x][y];
book = new boolean[x][y];
sum = 0;
for(int i = 0;i < x;i++) {
for(int j = 0;j < y;j++) {
biu[i][j] = new JButton();
biu[i][j].setIcon(new ImageIcon("Image\\SaoLei\\1.jpg"));
biu[i][j].addMouseListener(new BiuListener());
ls.add(biu[i][j]);
book[i][j] = false;
}
}
//设置计时器
time = new Timer(1000,new ActionListener() {
public void actionPerformed(ActionEvent e) {
int i = Integer.parseInt(tm0.getText());
tm0.setText(String.valueOf(i+1));
}
});
add(ls,BorderLayout.CENTER);
tim.add(Box.createHorizontalStrut(10));
tim.add(tu);
tim.add(tm0);
add(tim,BorderLayout.SOUTH);
// add(ls,BorderLayout.CENTER);
// add(bi,BorderLayout.WEST);
}
/**
* 设置并返回给定宽高的图片
* @param s为图片地址
* @param width为设置宽
* @param height为设置高
* @return ImageIcon对象
*/
ImageIcon setImageSize0(String s,int width,int height) {
ImageIcon im = new ImageIcon(s); //按如下方法设置任意宽高图片
im.setImage(im.getImage().getScaledInstance(width, height, Image.SCALE_DEFAULT));
return im;
}
/**
* 按钮监听器
* @author ds_surk
*
*/
class BiuListener extends MouseAdapter{
public void mouseClicked(MouseEvent e) {
if(tm0.getText().equals("0")) //点击第一个按钮时启动计时器
time.start();
int i,j,k;
int w = ls.getWidth()/y;
int h = ls.getHeight()/x;
JButton button = (JButton)e.getSource(); //获取事件源
for(i = 0;i < x;i++) {
for(k = 0;k < y;k++) {
if(biu[i][k] == button) { //找到对应按钮
// if(e.getModifiers() == InputEvent.BUTTON3_MASK) { //鼠标右键
// if(biu[i][k].getIcon().toString()==new ImageIcon("Image\\SaoLei\\1.jpg").toString()) {
// biu[i][k].setDisabledIcon((Icon)setImageSize0("Image\\SaoLei\\mine.jpg",w,h));
// biu[i][k].setEnabled(!biu[i][k].isEnabled());
// }
// return;
// }
for(j = 0;j < mines.length;j++) {
if(mines[j] == i*x+k+1) { //扫到雷了
biu[i][k].setIcon(setImageSize0("Image\\SaoLei\\2.jpg",w,h));
time.stop(); //停止计时
detonateMine(w,h); //引爆所有雷
popDialog0(); //弹出对话框
break;
}
}
if(j == mines.length) { //未扫到雷
searchMine(i,k,w,h); //查找周边雷并显示
if(sum == x * y - num) { //游戏胜利
time.stop(); //停止计时
if(Integer.parseInt(tm0.getText()) < max1)
addFile0(); // 记录排名
popDialog0(); //弹出对话框
}
}
return;
}
}
}
}
}
/**
* 创建文件存储对象
*/
class File0{
int a;
String s;
File0(){
a = 999999;
s = null;
}
}
/**
* 响应排行榜选项,打开排行榜
*/
void paiHang(){
int f10;
String type1=null,rerecord2=null;
if(num==10)
type1 = "简单";
else if(num==40)
type1 = "中等";
else
type1 = "困难";
JDialog pq0 = new JDialog(getck(),type1+"排行榜",true);
pq0.setBounds(600, 300, 300, 200);
Box pq1 = Box.createVerticalBox();
pq1.add(Box.createVerticalStrut(30));
JLabel[] jl = new JLabel[3];
jl[0] = new JLabel();
jl[1] = new JLabel();
jl[2] = new JLabel();
try {
File file = new File("Rank",type1+"排行.txt");
FileReader af1 = new FileReader(file);
BufferedReader af2 = new BufferedReader(af1);
for(f10 = 0;(rerecord2 = af2.readLine())!=null;f10++) {
jl[f10].setText(" 姓名:"+rerecord2 +" 用时:"+af2.readLine()+"s");
pq1.add(jl[f10]);
}
af2.close();
af1.close();
}catch(Exception e) {}
pq0.add(pq1);
pq0.setVisible(true);
}
/**
* 添加排名文件
*/
void addFile0() {
JDialog addfile = new JDialog(getck(),"破纪录!留下大名(最长8位)",true);
addfile.add(re);
addfile.setBounds(600, 300, 300, 200);
re.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
int f10;
String name0 = null;
if(num==10)
name0 = "简单";
else if(num==40)
name0 = "中等";
else
name0 = "困难";
File file10 = new File("Rank");
file10.mkdir();
File file = new File(file10,name0+"排行.txt");
if(!file.exists())
file.createNewFile();
FileReader af1 = new FileReader(file);
BufferedReader af2 = new BufferedReader(af1);
String record1 = null,record2 = null;
//获取最多8位字符
record2 = re.getText().substring(0, 8 Integer.parseInt(tm0.getText())) {
for(int f11 = 2;f11 > f10;f11--) {
f1[f11].a = f1[f11 - 1].a;
f1[f11].s = f1[f11 - 1].s;
}
break;
}
}
af2.close();
af1.close();
f1[f10].a = Integer.parseInt(tm0.getText());
if(record2==null || record2.equals(""))
record2="无名大虾";
f1[f10].s = record2;
FileWriter af = new FileWriter(file);
BufferedWriter af0 = new BufferedWriter(af);
for(f10 = 0;f10 < 3;f10++) {
if(f1[f10].a==999999) {
continue;
}
af0.write(f1[f10].s);
af0.newLine();
af0.write(String.valueOf(f1[f10].a));
af0.newLine();
}
max1 = f1[2].a;
af0.close();
af.close();
}catch(Exception ee) {
System.out.println(ee.toString());
}
addfile.setVisible(false);
}
});
addfile.setVisible(true);
}
/**
* 游戏失败,弹出对话框
*/
void popDialog0() {
JDialog jCkou = new JDialog(getck(), "游戏结束", true);
jCkou.setBounds(600, 300, 300, 200);
JButton b1,b2;
JLabel hint;
hint = new JLabel("您输了,下次加油。",JLabel.CENTER);
b1 = new JButton("退出");
b2 = new JButton("再来一局");
b1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
b2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ini();
jCkou.setVisible(false);
}
});
jCkou.setLayout(new FlowLayout());
Box b,c;
b = Box.createVerticalBox();
c = Box.createHorizontalBox();
if(sum == x * y - num) {
hint.setText("恭喜,您赢了! 用时:" + tm0.getText() + "s");
}
b.add(Box.createVerticalStrut(30));
b.add(hint);
b.add(Box.createVerticalStrut(60));
c.add(b1);
c.add(Box.createHorizontalStrut(80));
c.add(b2);
jCkou.add(b);
jCkou.add(c);
jCkou.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
ini();
jCkou.setVisible(false);
}
});
jCkou.setVisible(true);
}
/**
* 周边数组,配合searchArray()使用
* @author ds_surk
*
*/
class Aa {
int a,b;
}
/**
* 调用该方法返回周边位置数组
* @param i当前位置i
* @param k当前位置k
* @return 周边位置数组
*/
Aa[] searchArray(int i,int k) {
Aa [] a;
a = new Aa[8];
for(int ia = 0;ia < a.length;ia++) {
a[ia] = new Aa();
a[ia].a = -1;
a[ia].b = -1;
}
if(i - 1 >= 0 && k - 1 >= 0 && !book[i-1][k-1]) {
a[0].a = i - 1;
a[0].b = k - 1;
}
if(i - 1 >= 0 && !book[i-1][k]) {
a[1].a = i - 1;
a[1].b = k;
}
if(i - 1 >= 0 && k + 1 < y && !book[i-1][k+1]) {
a[2].a = i - 1;
a[2].b = k + 1;
}
if(k - 1 >= 0 && !book[i][k-1]) {
a[3].a = i;
a[3].b = k - 1;
}
if(k + 1 < y && !book[i][k+1]) {
a[4].a = i;
a[4].b = k + 1;
}
if(i + 1 < x && k - 1 >= 0 && !book[i+1][k-1]) {
a[5].a = i + 1;
a[5].b = k - 1;
}
if(i + 1 < x && !book[i+1][k]) {
a[6].a = i + 1;
a[6].b = k;
}
if(i + 1 < x && k + 1 < y && !book[i+1][k+1]) {
a[7].a = i + 1;
a[7].b = k + 1;
}
return a;
}
/**
* 搜索周边的雷,显示出周边雷数量
* 若当前点击位置周边无雷,则调用该方法自动"点击"周边按钮,递归调用,直到周边没有无雷的按钮。
*/
void searchMine(int i,int k,int w,int h) {
if(!book[i][k]) { //计数已点击按钮数
sum++;
}
book[i][k] = true; //标记当前位置
Aa[] a = searchArray(i,k).clone(); //返回周边位置
int fa = 0; //周围雷的数量
for(int jm = 0;jm < mines.length;jm++) {
for(Aa ia:a) {
if(ia.a == -1)
continue;
if(mines[jm] == ia.a * x + ia.b + 1) {
fa++;
break;
}
}
}
//按照相应的雷数替换相应图片
switch(fa) {
case 1:
biu[i][k].setIcon(setImageSize0("Image\\SaoLei\\d1.jpg",w,h));
break;
case 2:
biu[i][k].setIcon(setImageSize0("Image\\SaoLei\\d2.jpg",w,h));
break;
case 3:
biu[i][k].setIcon(setImageSize0("Image\\SaoLei\\d3.jpg",w,h));
break;
case 4:
biu[i][k].setIcon(setImageSize0("Image\\SaoLei\\d4.jpg",w,h));
break;
case 5:
biu[i][k].setIcon(setImageSize0("Image\\SaoLei\\d5.jpg",w,h));
break;
case 6:
biu[i][k].setIcon(setImageSize0("Image\\SaoLei\\d6.jpg",w,h));
break;
case 7:
biu[i][k].setIcon(setImageSize0("Image\\SaoLei\\d7.jpg",w,h));
break;
case 8:
biu[i][k].setIcon(setImageSize0("Image\\SaoLei\\d8.jpg",w,h));
break;
case 0:
biu[i][k].setIcon(new ImageIcon(""));
for(Aa ia:a) {
if(ia.a == -1)
continue;
searchMine(ia.a,ia.b,w,h); //递归调用
}
break;
} //switch
}
/**
* 引爆所有的雷
*/
void detonateMine(int w,int h) {
for(int ii = 0;ii < x;ii++) { //引爆所有雷
for(int kk = 0;kk < y;kk++) {
for(int jj = 0;jj < mines.length;jj++) {
if(ii*x+kk+1 == mines[jj]) {
book[ii][kk] = true;
biu[ii][kk].setIcon(setImageSize0("Image\\SaoLei\\2.jpg",w,h));
// try {
// Thread.sleep(200); //延时执行
// }catch(Exception ee) {}
}
}
}
}
}
/**
* 设置网格行列
* @param x = row
* @param y = column
*/
void setGrid(int x,int y) {
this.x = x;
this.y = y;
}
/**
* 随机产生mine位置
* @param q为设置的mine数
*/
void setRand(int q) {
mines = new int[q];
for(int i:mines) i = 0;
mines[0] = -1;
for(int i = 0;i < mines.length;i++) {
int rand = 0,j;
boolean flag = false;
while(!flag) {
rand = (int)(Math.random()*x*y);
if(rand <= 0 || rand > x*y) continue;
if(mines[i]==-1) break;
for(j = 0;j < mines.length;j++) {
if(rand == mines[j])
break;
}
if(j == mines.length) flag = true;
}
mines[i] = rand;
}
Arrays.sort(mines);
}
/**
* 重新初始化
*/
void ini() {
ls.setVisible(false); //隐藏当前容器
remove(ls); //移除当前容器
time.stop(); //停止计时
init1(); //重新初始化
}
/**
* 响应设置选项,启动设置窗口
* @author ds_surk
*
*/
class Set0 implements ActionListener{
JPanel setJ;
JLabel setJi;
JButton j,j0;
JRadioButton j1 = new JRadioButton("简单:9X9网格,10个雷"); //单选按钮
JRadioButton j2 = new JRadioButton("中等:16X16网格,40个雷");
JRadioButton j3 = new JRadioButton("困难:16X30网格,99个雷");
Box b,b1;
ButtonGroup bg = new ButtonGroup(); //按钮组
JRadioButton jc = j1,ja = j1; //存储所选选项
class Se extends JFrame implements ItemListener{
Se(){}
Se(String s,int x,int y,int width,int height){
inits(s);
setBounds(x,y,width,height);
setLocationRelativeTo(null);
setVisible(true);
setDefaultCloseOperation(2);
}
void inits(String s) {
setTitle(s);
setIconImage(getToolkit().getImage("Image\\SaoLei\\Se.jpg"));
setJ = new JPanel();
b = Box.createVerticalBox();
b1 = Box.createHorizontalBox();
setJi = new JLabel("难度:",JLabel.CENTER);
j = new JButton("确定");
j0 = new JButton("取消");
bg.add(j1);
bg.add(j2);
bg.add(j3);
jc.setSelected(true);
j.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
jc = ja;
jc.setSelected(true);
if(jc == j1) {
x = y = 9;
num = 10;
}
else if(jc == j2) {
x = y = 16;
num = 40;
}
else {
x = 16;
y = 30;
num = 99;
}
ini();
dispose(); //销毁窗口
}
});
j0.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
dispose();
}
});
j1.addItemListener(this);
j2.addItemListener(this);
j3.addItemListener(this);
b.add(Box.createVerticalStrut(10));
b.add(setJi);
b.add(Box.createVerticalStrut(10));
b.add(j1);
b.add(Box.createVerticalStrut(5));
b.add(j2);
b.add(Box.createVerticalStrut(5));
b.add(j3);
b.add(Box.createVerticalStrut(30));
b1.add(j);
b1.add(Box.createHorizontalStrut(80));
b1.add(j0);
setJ.add(b);
setJ.add(b1);
add(setJ);
}
public void itemStateChanged(ItemEvent e) {
ja = (JRadioButton)e.getSource();
}
}
public void actionPerformed(ActionEvent e) {
Se se = new Se("设置",700,400,300,300);
}
} //Set0
} //GuiSl
/**
* 响应help选项,启动说明界面
* @author ds_surk
*
*/
class Help implements ActionListener{
class Hel extends JFrame{
Hel(){}
Hel(String s,int x,int y,int width,int height){
inits(s);
setBounds(x,y,width,height);
setVisible(true);
setDefaultCloseOperation(2); //设置关闭方式为关闭当前窗口
}
void inits(String s) {
setTitle(s);
setIconImage(getToolkit().getImage("Image\\SaoLei\\help.jpg"));
JPanel jp0=new JPanel();
JPanel jp1=new JPanel();
Box jBox0 = Box.createVerticalBox();
JButton j = new JButton("确定");
jBox0.add(Box.createHorizontalStrut(35));
jBox0.add(Box.createVerticalStrut(35));
jBox0.add(new JLabel("本程序为自制游戏,作为Java语言学习检验。",JLabel.CENTER));
jBox0.add(Box.createVerticalStrut(5));
jBox0.add(new JLabel("玩法与扫雷相同。",JLabel.CENTER));
jBox0.add(Box.createVerticalStrut(15));
jBox0.add(new JLabel("如有疑问,请联系开发者。",JLabel.CENTER));
jBox0.add(Box.createVerticalStrut(5));
jBox0.add(new JLabel("开发者:ds_surk",JLabel.CENTER));
jBox0.add(Box.createVerticalStrut(10));
jp1.add(j);
jBox0.add(jp1);
jp0.add(jBox0);
j.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
dispose(); //关闭当前窗口
} });
add(jp0);
}
}
public void actionPerformed(ActionEvent e) {
Hel he = new Hel("Help",570,300,300,260);
}
}
/**
* 响应关于选项,启动说明界面
* @author ds_surk
*
*/
class GYu implements ActionListener{
class Gyu extends JFrame{
Gyu(){}
Gyu(String s,int x,int y,int width,int height){
inits(s);
setBounds(x,y,width,height);
setVisible(true);
setDefaultCloseOperation(2); //设置关闭方式为关闭当前窗口
}
void inits(String s) {
setTitle(s);
setIconImage(getToolkit().getImage("Image\\SaoLei\\gyu.jpg"));
JPanel jp0=new JPanel();
JPanel jp1 = new JPanel();
Box jBox = Box.createVerticalBox();
JLabel title = new JLabel("本程序由Java语言编写!",JLabel.CENTER);
JButton j = new JButton("确定");
jBox.add(Box.createHorizontalStrut(35));
title.setIcon(new ImageIcon("Image\\SaoLei\\index.jpg"));
jBox.add(title);
jBox.add(Box.createVerticalStrut(5));
jBox.add(new JLabel("——————————————",JLabel.CENTER));
jBox.add(new JLabel("名称:扫雷"));
jBox.add(Box.createVerticalStrut(5));
jBox.add(new JLabel("版本:1.0"));
jBox.add(Box.createVerticalStrut(5));
jBox.add(new JLabel("开发者:ds_surk"));
jBox.add(Box.createVerticalStrut(5));
jBox.add(new JLabel("版权所有,未经许可,禁止作为商用。",JLabel.CENTER));
jBox.add(Box.createVerticalStrut(10));
jp1.add(j);
jBox.add(jp1);
jp0.add(jBox);
j.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
dispose(); //关闭当前窗口
} });
add(jp0);
}
}
public void actionPerformed(ActionEvent e) {
Gyu yu = new Gyu("关于",590,400,280,280);
}
}
本文未经允许,不可转载,或作为他用。
附上打包链接(可直接使用):https://download.csdn.net/download/hunt_er/10589346