1 .主类 |
package s1213扫雷 6 ; |
//3.改变难度 关闭旧窗体,新建一个窗体,执行所有原来的代码 |
//7.菜单栏选项的时间,应该放在public void actionPerformed(ActionEvent e) 这个方法里面 |
//8尽量使用if+elseif 少用if+else 因为一旦情况发生改变,else很容易出现判断失误的情况 |
//10.每一次更改状态变量都要写上条件,因为以后更改程序,有可能发生条件变化,原代码就会出错!!! |
//12.打开和读取文件的功能 |
import javax.swing.ImageIcon; |
import javax.swing.JFileChooser; |
import javax.swing.JFrame; |
import javax.swing.JLabel; |
import javax.swing.JMenu; |
import javax.swing.JMenuBar; |
import javax.swing.JMenuItem; |
import javax.swing.JOptionPane; |
import java.awt.Dimension; |
import java.awt.FlowLayout; |
import java.awt.event.MouseEvent; |
import java.awt.event.MouseListener; |
import java.util.*; |
public class Main1213 extends JFrame { |
|
int bombNum= 30 ; //地雷数目 |
int nearBombNum[][]= new int [ 100 ][ 100 ]; //存储这个格子周围地雷的数目 |
int stackNum= 0 ; //表示堆栈中有多少个元素,用作while循环的终止条件 |
Boolean isBomb[][]= new Boolean [ 50 ][ 50 ]; //存储格子是不是地雷,false(不是地雷),true(地雷) |
Mybutton button[][]= new Mybutton[ 100 ][ 100 ]; //Mybutton类型的数组,专门存放按钮,方便得到按钮的x,y参数(坐标参数) |
Stack<Mybutton> a= new Stack<Mybutton>(); //创建一个堆栈对象,用来开图 |
static Main1213 b= null ; |
|
|
ImageIcon redFlagIcon= new ImageIcon( "E:/Michael/javaImage/扫雷图片/1.jpg" ); //红旗 |
ImageIcon clickIcon= new ImageIcon( "E:/Michael/javaImage/扫雷图片/2.jpg" ); //鼠标左键单击时的图标 |
ImageIcon InitialIcon= new ImageIcon( "E:/Michael/javaImage/扫雷图片/3.png" ); //初始图片 |
ImageIcon mouseOverIcon= new ImageIcon( "E:/Michael/javaImage/扫雷图片/4.png" ); //鼠标覆盖时的图标 |
ImageIcon bombIcon= new ImageIcon( "E:/Michael/javaImage/扫雷图片/5.jpg" ); //地雷的图标 |
|
//地雷数从1-8的对应图标,BombNumberPicture[0]对应图标地雷数为1,BombNumberPicture[7]对应图标地雷数为8 |
ImageIcon BombNumberPicture[]={ |
new ImageIcon( "E:/Michael/javaImage/扫雷图片/6.jpg" ), |
new ImageIcon( "E:/Michael/javaImage/扫雷图片/7.jpg" ), |
new ImageIcon( "E:/Michael/javaImage/扫雷图片/8.jpg" ), |
new ImageIcon( "E:/Michael/javaImage/扫雷图片/9.jpg" ), |
new ImageIcon( "E:/Michael/javaImage/扫雷图片/10.jpg" ), |
new ImageIcon( "E:/Michael/javaImage/扫雷图片/11.jpg" ), |
new ImageIcon( "E:/Michael/javaImage/扫雷图片/12.jpg" ), |
new ImageIcon( "E:/Michael/javaImage/扫雷图片/13.jpg" ),}; |
|
public static void main(String[] args) |
{ b= new Main1213(); |
b.setBomb(); //布雷 |
b.Mymenu(); //添加菜单栏 |
b.init(); //setVisiable的位置很重要,a.Mymenu();a.init(); 顺序交换就看不到菜单栏了。 |
b.setButton(); //在界面中添加按钮和监听事件 |
} |
|
public void init() |
{ this .setTitle( "扫雷" ); //设置窗体的标题 |
this .setLocationRelativeTo( null ); //设置窗体出现位置居中 |
this .setDefaultCloseOperation( 3 ); //设置窗体的关闭操作 |
this .setResizable( true ); //设置禁止调整窗体的大小 |
this .setIconImage(( new ImageIcon( "E:/Michael/javaImage/扫雷图片/bomb.png" ).getImage())); //设置标题栏图标 |
this .setSize( 430 , 500 ); //设置窗体的大小 |
this .setLocationRelativeTo( null ); //设置窗体出现在屏幕中间 |
this .setLayout( new FlowLayout(FlowLayout.LEFT, 0 , 0 )); |
this .setVisible( true ); |
} |
|
public void setButton() //绘制界面,鼠标对界面的操作事件(地雷格子) |
{ |
//事件监听*************************************************************************************************** |
MouseListener mouseListener= new MouseListener() |
{ |
public void mousePressed(MouseEvent e) |
{ |
//右键点击******************************************************************** |
if (e.getButton()==MouseEvent.BUTTON3) |
{ |
Mybutton btn = (Mybutton)e.getSource(); //得到事件源对象,并强制转型为Mybutton |
int flagAndBomb= 0 ; |
|
if (btn.status== 0 ) //如果该按钮状态为没翻转过 |
{btn.setIcon(redFlagIcon);btn.setStatus( 4 );} //改变图标为redFlagIcon,并设置为状态3(红旗) |
else if (btn.status== 4 ) //如果该按钮状态为红旗 |
{btn.setIcon(InitialIcon);btn.setStatus( 0 );} //改变图标为InitialIcon(初始图标) |
else if (btn.status== 1 ) //如果是已经翻开的图标 |
{ |
int x=btn.x, y=btn.y; //x,y用来表示当前按钮的坐标 |
checkBomb(x, y); |
//如果标记的红旗下面不是地雷,那么游戏结束********************************* |
} |
|
|
|
//胜利判断************************** |
for ( int i= 0 ;i< 20 ;i++) |
for ( int j= 0 ;j< 20 ;j++) |
{ if (isBomb[i][j]&&button[i][j].status== 4 ) |
flagAndBomb++; |
} |
if (flagAndBomb==bombNum) |
{ for ( int i= 0 ;i< 20 ;i++) //判断胜利后开全图 |
for ( int j= 0 ;j< 20 ;j++) |
{changeBombIcon(button[i][j]);} |
JOptionPane.showMessageDialog( null , "你胜利了" );} |
//********************************** |
} |
//*************************************************************************** |
|
|
//左键点击******************************************************************** |
if (e.getButton()==MouseEvent.BUTTON1) |
{ Mybutton btn = (Mybutton)e.getSource(); |
if (btn.status== 0 ) |
{ btn.setStatus( 1 ); |
if (!isBomb[btn.x][btn.y]) //如果点击不是地雷 |
{ findBomb(); //遍历地图,找到所有位置周围的地雷数目 |
showBomb(btn); //根据周围地雷数目,更换图标 |
|
} |
|
if (isBomb[btn.x][btn.y]) //如果鼠标点击是地雷 |
{ for ( int i= 0 ;i< 20 ;i++) //找到所有的地雷 |
for ( int j= 0 ;j< 20 ;j++) |
{ button[i][j].setStatus( 1 ); //改变所有按钮的状态变量为1(翻转状态) |
if (isBomb[i][j]) button[i][j].setIcon(bombIcon);} //找到地雷并改变图标为bombIcon(地雷图标) |
JOptionPane.showMessageDialog( null , "游戏结束" ); //弹出消息提示框,提示游戏结束 |
} |
} |
} |
//左键点击********************************************************************** |
} |
//计算点击处周围8个格子中的红旗数,保存在flag,用count来记录红旗和地雷的吻合数目 |
public void checkBomb( int x, int y) { |
int bomb= 0 ,flag= 0 ; |
for ( int i= 0 ;i< 8 ;i++) |
{ |
if ( new Mybutton(getX(x,i),getY(y,i)).locationLegalJudge()) //边界判断 |
{ |
|
if (button[getX(x,i)][getY(y,i)].status== 3 ||button[getX(x,i)][getY(y,i)].status== 4 ) |
{ |
flag++; //如果格子状态表示红旗,那么红旗数目+1 |
if (isBomb[getX(x,i)][getY(y,i)]) |
{bomb++; } |
} |
} |
} |
|
|
//如果红旗和地雷吻合,则开图,不吻合就结束游戏,共2种情况*************************************** |
if (bomb==nearBombNum[x][y]) //如果周围雷数和判断一样 |
{ |
for ( int i= 0 ;i< 8 ;i++) //周围8个格子,每个格子判断一次 |
{ |
if ( new Mybutton(getX(x,i),getY(y,i)).locationLegalJudge()&&!isBomb[x][y]) //边界判断,而且不是地雷 |
{ |
changeBombIcon(button[getX(x,i)][getY(y,i)]); //点击处左上角判断 |
if (nearBombNum[getX(x,i)][getY(y,i)]== 0 &&!isBomb[getX(x,i)][getY(y,i)]) |
showBomb(button[getX(x,i)][getY(y,i)]); |
} |
} |
|
} |
//如果红旗和地雷吻合,则开图,不吻合就结束游戏,共2种情况*************************************** |
|
//如果标记的红旗下面不是地雷,那么游戏结束********************************* |
if ((bomb!=nearBombNum[x][y]&&flag>=nearBombNum[x][y])) |
{ |
for ( int i= 0 ;i< 20 ;i++) //找到所有的地雷 |
for ( int j= 0 ;j< 20 ;j++) |
{ button[i][j].setStatus( 1 ); //改变所有按钮的状态变量为1(翻转状态) |
if (isBomb[i][j]) button[i][j].setIcon(bombIcon);} //找到地雷并改变图标为bombIcon(地雷图标) |
JOptionPane.showMessageDialog( null , "游戏结束" ); //弹出消息提示框,提示游戏结束 |
} |
} |
|
public void mouseEntered(MouseEvent e) |
{ |
Mybutton btn=(Mybutton)e.getSource(); //要强制转型 |
if (btn.status== 0 ) btn.setIcon(mouseOverIcon); //如果还没有翻转,那么改变按钮图案 |
} |
|
public void mouseExited(MouseEvent e) |
{ |
Mybutton btn=(Mybutton)e.getSource(); //要强制转型,得到事件源 |
if (btn.status== 0 ) btn.setIcon(InitialIcon); //如果按钮还未翻转,那么改变按钮图案 |
} |
public void mouseReleased(MouseEvent e) |
{} |
public void mouseClicked(MouseEvent e) |
{} |
|
}; |
//******************************************************************************************************* |
|
//绘制游戏界面************************************************************************************************ |
for ( int i= 0 ;i< 20 ;i++) //生成界面按钮20行20列 |
for ( int j= 0 ;j< 20 ;j++) |
{ |
Mybutton jb= new Mybutton(i,j); |
jb.setPreferredSize( new Dimension( 20 , 20 )); |
jb.addMouseListener(mouseListener); //要将new mouselistener的代码放到前面这行代码才不会出错 |
button[i][j]=jb; //通过这种方式就可以根据i,j唯一确定每个按钮 |
this .add(jb); //界面添加按钮 |
} |
|
JLabel jl = new JLabel(); //用来计时的标签 |
JLabel j2 = new JLabel( "游戏计时:" ); |
this .add(j2); |
this .add(jl); |
//计时功能********************************************* |
TimerTask task = new TimerTask() |
{ int n= 0 ; |
public void run() |
{ jl.setText( "" +n); n++;} //计时++ |
}; |
Timer timer = new Timer(); |
timer.schedule(task, 0 , 1000 ); |
//计时功能********************************************* |
|
//绘制游戏界面************************************************************************************************ |
} |
public void setBomb() //布雷 |
{ for ( int i= 0 ;i< 20 ;i++) //遍历地图,将所有格子的地雷状态变量都初始化为0,0表示不是地雷 |
for ( int j= 0 ;j< 20 ;j++) //遍历地图,将所有格子的地雷状态变量都初始化为0,0表示不是地雷 |
isBomb[i][j]= false ; //遍历地图,将所有格子的地雷状态变量都初始化为0,0表示不是地雷 |
int n= 0 ; |
while (n<bombNum) //当n<地雷数,就一直循环执行 |
{ int x= new Random().nextInt( 20 ); //随机产生行数 |
int y= new Random().nextInt( 20 ); //随机产生列数 |
if (!isBomb[x][y]) {isBomb[x][y]=!isBomb[x][y];n++;} //如果随机产生的位置原来的状态是没有地雷,将地雷状态改变,地雷数加1 |
} |
} |
|
public void findBomb() //找出地图中所有位置周围地雷的数目,保存在nearBombNum[x][y]中 |
{ for ( int x= 0 ;x< 20 ;x++) //遍历整个地图 |
for ( int y= 0 ;y< 20 ;y++) |
{ |
if (!isBomb[x][y]) //只有当这个位置不是地雷的时候才执行查找周围地雷数的代码 |
{ |
int n= 0 ; //n记录周围地雷的数目 |
for ( int i= 0 ;i< 8 ;i++) |
{ |
if ( new Mybutton(getX(x,i),getY(y,i)).locationLegalJudge()&&isBomb[getX(x,i)][getY(y,i)]) //边界判断 |
{ |
n++; |
} |
} |
setNearBombNum(x,y,n); |
|
} |
} |
} |
|
|
public void showBomb(Mybutton btn) //点击后更改图标和开图功能 |
{ |
int x=btn.x, y=btn.y,k=nearBombNum[x][y]; //x,y用来表示当前按钮的坐标,k用来表示是按钮周围的地雷数 |
if (btn.status== 0 ) btn.setStatus( 1 ); //表示访问过了 |
if (k== 0 ) //如果这个格子周围没有地雷 |
{ |
|
for ( int i= 0 ;i< 8 ;i++) |
{ |
if ( new Mybutton(getX(x,i),getY(y,i)).locationLegalJudge()&&!isBomb[getX(x,i)][getY(y,i)]) //边界判断 |
{ |
changeBombIcon(button[getX(x,i)][getY(y,i)]); //点击处左上角判断 |
if (nearBombNum[getX(x,i)][getY(y,i)]== 0 &&button[getX(x,i)][getY(y,i)].status== 0 ) { |
a.push(button[getX(x,i)][getY(y,i)]); |
stackNum++; |
} |
} |
} |
|
while (stackNum> 0 ) //深度优先遍历,先将所有空格加进去,再倒出来 |
{ stackNum--;showBomb(a.pop());} |
} |
|
else changeBombIcon(btn); //如果点击的不是空格,那么直接改变按钮图案 |
} |
|
public void changeBombIcon(Mybutton btn) //根据周围地雷数,改变按钮图标 |
{ |
int nearBombNumber=nearBombNum[btn.x][btn.y]; //k用来表示是按钮周围的地雷数 |
|
if (nearBombNumber== 0 ){ |
btn.setIcon(mouseOverIcon); |
if (isBomb[btn.x][btn.y]) |
{btn.setIcon(redFlagIcon);btn.setStatus( 3 );} //如果是地雷,那么就改变图标 |
} |
else |
{ |
btn.setIcon(BombNumberPicture[nearBombNumber- 1 ]); btn.setStatus( 1 ); |
} |
|
} |
//**************************************菜单栏*************************************************// |
public void Mymenu() |
{ |
JMenu file,edit,help,nandu; //声明JMenu类对象 |
JMenuItem newgame,exit,copy,chuji,zhongji,gaoji,author,wanfa; //声明menuitem类对象 |
//初始菜单项 |
|
|
|
newgame= new JMenuItem( "新游戏" , new ImageIcon( "C:/Users/Administrator/Desktop/images/2.jpg" )); //创建menuItem对象 |
exit= new JMenuItem( "关闭" ){{b.dispose();}}; //创建menuItem对象 |
copy= new JMenuItem( "保存战绩" ){ //创建menuItem对象 |
{ addActionListener( |
e->{ |
JFileChooser a= new JFileChooser(); //打开文件路径程序框 |
a.setDialogTitle( "另存为" ); |
a.showSaveDialog( null ) ; //注意showSaveDialog和showOpenDialog的区别 |
}); |
}}; |
|
author= new JMenuItem( "作者" ){ //创建menuItem对象 |
{ addActionListener( |
e->JOptionPane.showMessageDialog( null , "游戏作者:贺思源 制作时间:2014.12.13" )); |
}}; |
|
wanfa= new JMenuItem( "玩法" ); //创建menuItem对象 |
chuji= new JMenuItem( "初级" ); //创建menuItem对象 |
zhongji= new JMenuItem( "中级" ); //创建menuItem对象 |
gaoji= new JMenuItem( "高级" ); //创建menuItem对象 |
|
|
nandu= new JMenu( "难度" ){{add(chuji);add(zhongji);add(gaoji);}}; //创建menuItem对象 |
help= new JMenu( "帮助" ){{add(author);add(wanfa); }}; //创建JMenu对象 |
file= new JMenu( "游戏(G)" ){{setMnemonic( 'G' );add(newgame);add(nandu);addSeparator();add(exit);}}; //创建JMenu对象 |
edit= new JMenu( "编辑" ){{add(copy);}}; |
JMenuBar menubar= new JMenuBar(){{add(file);add(help);add(edit);}}; //创建menubar对象 |
|
|
|
chuji.addActionListener( e-> |
{ |
this .dispose(); //关闭旧窗体 |
Main1213 s2= new Main1213(); |
s2.setbombNum( 30 ); |
s2.setBomb(); //布雷 |
s2.Mymenu(); //添加菜单栏 |
s2.init(); //setVisiable的位置很重要,a.Mymenu();a.init(); 顺序交换就看不到菜单栏了。 |
s2.setButton(); //在界面中添加按钮和监听事件 |
}); |
|
zhongji.addActionListener( e-> |
{ |
this .dispose(); //关闭旧窗体 |
Main1213 s2= new Main1213(); |
s2.setbombNum( 60 ); |
s2.setBomb(); //布雷 |
s2.Mymenu(); //添加菜单栏 |
s2.init(); //setVisiable的位置很重要,a.Mymenu();a.init(); 顺序交换就看不到菜单栏了。 |
s2.setButton(); //在界面中添加按钮和监听事件 |
}); |
|
gaoji.addActionListener( e-> |
{ |
this .dispose(); //关闭旧窗体 |
Main1213 s2= new Main1213(); |
s2.setbombNum( 90 ); |
s2.setBomb(); //布雷 |
s2.Mymenu(); //添加菜单栏 |
s2.init(); //setVisiable的位置很重要,a.Mymenu();a.init(); 顺序交换就看不到菜单栏了。 |
s2.setButton(); //在界面中添加按钮和监听事件 |
}); |
|
exit.addActionListener(e-> this .dispose()); //关闭游戏 |
this .setJMenuBar(menubar); //设置menuBar |
} |
//********************************************************************************************// |
|
public void setbombNum( int x) //设置地雷数目 |
{ bombNum=x;} |
public Mybutton getButton( int x, int y) { |
return button[x][y]; |
} |
|
//根据x坐标和index,得到周围第i个格子的x坐标 |
public int getX( int x, int index) { |
int xLocation[]={x- 1 ,x,x+ 1 ,x- 1 ,x+ 1 ,x- 1 ,x,x+ 1 ,}; |
return xLocation[index]; |
} |
|
//根据y坐标和index,得到周围第i个格子的y坐标 |
public int getY( int y, int index) { |
int yLocation[]={y+ 1 ,y+ 1 ,y+ 1 ,y,y,y- 1 ,y- 1 ,y- 1 }; |
return yLocation[index]; |
} |
public int [][] getNearBombNum() { |
return nearBombNum; |
} |
public void setNearBombNum( int x, int y, int bombNumber) { |
nearBombNum[x][y]=bombNumber; |
} |
} |
2 .Mybutton类 |
package s1213扫雷 6 ; |
import javax.swing.ImageIcon; |
import javax.swing.JButton; |
import javax.swing.border.EmptyBorder; |
public class Mybutton extends JButton { |
int status; // 0(未翻转),1(翻转),3(地雷),4(红旗) |
int x, y; |
ImageIcon i1 = new ImageIcon( "E:/Michael/javaImage/扫雷图片/3.png" ); // 初始图片 |
EmptyBorder o = new EmptyBorder( 2 , 2 , 0 , 0 ); // 生成按钮边界对象 |
Mybutton() { // 构造方法 |
this .setIcon(i1); // 给按钮添加图标 |
this .setBorder(o); // 改变按钮边界 |
} |
Mybutton( int x, int y) { // 调用本类构造方法 |
this (); |
this .x = x; |
this .y = y; |
} |
public boolean locationLegalJudge() { |
return this .x >= 0 && this .x <= 19 && this .y >= 0 && this .y <= 19 ; |
} |
public void setStatus( int x) // 改变按钮的状态变量方法 |
{ |
this .status = x; |
} |
public int getStatus() { |
return status; |
} |
} |
初级程序员
by: 彭浩 发表于:2016-11-22 09:22:40 顶(0) | 踩(0) 回复
图片 包中没有啊
回复评论