我初学java,模仿写了个扫雷,只要将代码中wav文件路径设置正确,即可正常运行,希望大家狠批特批。对于布局以及背景音乐的问题,不知还有什么更好的方法?/**
@version 1.0 2006-12-24
@author widewolf
@e-mail [email protected]
*/
import java.applet.*;
import java.net.URL;
import sun.audio.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class sweepmine
{
public static void main(String[] args)
{
sweepmine initer = new sweepmine();
initer.init();
try//背景音乐
{
/**AudioClip ac = Applet.newAudioClip(new URL("file:/c:/security.wav"));
ac.loop();
这里用了Applet里的方法,倒是能行,但有两问题:1,播放原生wav好像能行,但在循环播放一个从mp3转化而来的wav文件时cpu(PD820)占有率竟然持续高达100%;
2 ,在调用不相关的菜单事件时,停止了播放。*/ InputStream in = new FileInputStream ("c:\\爱的废墟.wav");
AudioStream as = new AudioStream (in);
/**AudioData data = as.getData ();
这用了sun.audio.*和java.io.*来实现背景音乐,没有编译的是播放一次,原生wav和转化而来的wav都没有问题,循环播放时原生wav没有问题,转化而来的有一个问题(就上面这句):
java.io.IOException: could not create AudioData object
ContinuousAudioDataStream cas = new ContinuousAudioDataStream (data);
AudioPlayer.player.start (cas);*/ AudioPlayer.player.start (as);
}
catch (IOException e)
{
System.err.println(e);
}
}
void init()
{
mineframe = new frame(9,9,10);
JMenuBar menubar = new JMenuBar();
mineframe.setJMenuBar(menubar);
JMenu gamemenu= new JMenu("游戏(G)");
menubar.add(gamemenu);
JMenu helpmenu= new JMenu("帮助(H)");
menubar.add(helpmenu);
Action middleaction =new menuaction("开局(N)");
JMenuItem start = gamemenu.add(middleaction);
gamemenu.addSeparator();
ActionListener listener =new menulistener();
JMenuItem junior = new JMenuItem("初级(J)");
junior.setName("junior");
junior.addActionListener(listener);
gamemenu.add(junior);
JMenuItem middle = new JMenuItem("中级(M)");
middle.setName("middle");//下面监听器要用
middle.addActionListener(listener);
gamemenu.add(middle);
JMenuItem senior = new JMenuItem("高级(S)");
senior.setName("senior");
senior.addActionListener(listener);
gamemenu.add(senior);
mineframe.setTitle("扫雷");
mineframe.setSize(189,232);//因面板没有布局,所以只能制定框架的大小
mineframe.setLocation(400,300);
mineframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mineframe.setVisible(true);
mineframe.setResizable(false);
}
private class menulistener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
JMenuItem temp=(JMenuItem)event.getSource();
String name = temp.getName();
mineframe.remove(mineframe.minepanel);//移除原面板
if(name.equals("middle"))
{
mineframe.minepanel = new panel(16,16,40);//重新构造面板,面板为框架的属性
mineframe.setSize(329,372);
}
else if(name.equals("junior"))
{
mineframe.minepanel = new panel(9,9,10);
mineframe.setSize(189,232);
}
else
{
mineframe.minepanel = new panel(30,16,99);
mineframe.setSize(609,372);
}
mineframe.add(mineframe.minepanel);
mineframe.minepanel.laymine();
mineframe.validate();//刷新界面
}
}
private class menuaction extends AbstractAction//菜单动作
{
public menuaction(String s)
{
super(s);
}
public void actionPerformed(ActionEvent event)
{
mineframe.minepanel.refresh();
}
}
frame mineframe;//框架为主类的属性
}
class frame extends JFrame
{
public frame(int m,int n,int o)
{
minepanel = new panel(m,n,o);
add(minepanel);
minepanel.laymine();
}
panel minepanel;
}
@version 1.0 2006-12-24
@author widewolf
@e-mail [email protected]
*/
import java.applet.*;
import java.net.URL;
import sun.audio.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class sweepmine
{
public static void main(String[] args)
{
sweepmine initer = new sweepmine();
initer.init();
try//背景音乐
{
/**AudioClip ac = Applet.newAudioClip(new URL("file:/c:/security.wav"));
ac.loop();
这里用了Applet里的方法,倒是能行,但有两问题:1,播放原生wav好像能行,但在循环播放一个从mp3转化而来的wav文件时cpu(PD820)占有率竟然持续高达100%;
2 ,在调用不相关的菜单事件时,停止了播放。*/ InputStream in = new FileInputStream ("c:\\爱的废墟.wav");
AudioStream as = new AudioStream (in);
/**AudioData data = as.getData ();
这用了sun.audio.*和java.io.*来实现背景音乐,没有编译的是播放一次,原生wav和转化而来的wav都没有问题,循环播放时原生wav没有问题,转化而来的有一个问题(就上面这句):
java.io.IOException: could not create AudioData object
ContinuousAudioDataStream cas = new ContinuousAudioDataStream (data);
AudioPlayer.player.start (cas);*/ AudioPlayer.player.start (as);
}
catch (IOException e)
{
System.err.println(e);
}
}
void init()
{
mineframe = new frame(9,9,10);
JMenuBar menubar = new JMenuBar();
mineframe.setJMenuBar(menubar);
JMenu gamemenu= new JMenu("游戏(G)");
menubar.add(gamemenu);
JMenu helpmenu= new JMenu("帮助(H)");
menubar.add(helpmenu);
Action middleaction =new menuaction("开局(N)");
JMenuItem start = gamemenu.add(middleaction);
gamemenu.addSeparator();
ActionListener listener =new menulistener();
JMenuItem junior = new JMenuItem("初级(J)");
junior.setName("junior");
junior.addActionListener(listener);
gamemenu.add(junior);
JMenuItem middle = new JMenuItem("中级(M)");
middle.setName("middle");//下面监听器要用
middle.addActionListener(listener);
gamemenu.add(middle);
JMenuItem senior = new JMenuItem("高级(S)");
senior.setName("senior");
senior.addActionListener(listener);
gamemenu.add(senior);
mineframe.setTitle("扫雷");
mineframe.setSize(189,232);//因面板没有布局,所以只能制定框架的大小
mineframe.setLocation(400,300);
mineframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mineframe.setVisible(true);
mineframe.setResizable(false);
}
private class menulistener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
JMenuItem temp=(JMenuItem)event.getSource();
String name = temp.getName();
mineframe.remove(mineframe.minepanel);//移除原面板
if(name.equals("middle"))
{
mineframe.minepanel = new panel(16,16,40);//重新构造面板,面板为框架的属性
mineframe.setSize(329,372);
}
else if(name.equals("junior"))
{
mineframe.minepanel = new panel(9,9,10);
mineframe.setSize(189,232);
}
else
{
mineframe.minepanel = new panel(30,16,99);
mineframe.setSize(609,372);
}
mineframe.add(mineframe.minepanel);
mineframe.minepanel.laymine();
mineframe.validate();//刷新界面
}
}
private class menuaction extends AbstractAction//菜单动作
{
public menuaction(String s)
{
super(s);
}
public void actionPerformed(ActionEvent event)
{
mineframe.minepanel.refresh();
}
}
frame mineframe;//框架为主类的属性
}
class frame extends JFrame
{
public frame(int m,int n,int o)
{
minepanel = new panel(m,n,o);
add(minepanel);
minepanel.laymine();
}
panel minepanel;
}
class panel extends JPanel
{
public panel(int m,int n,int count)
{
setLayout(null);//不知道有没有三维布局?
button = new JButton[m][n];
textfield = new JTextField[m][n];
row=m;
cols=n;
minecount=count;
for( int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
button[i][j]= new JButton();
textfield [i][j]= new JTextField();
add(button[i][j],null);
add(textfield[i][j],null);
button[i][j].setBounds(new Rectangle(i*20, j*20,20, 20));
textfield [i][j].setBounds(new Rectangle(i*20, j*20,20, 20));//用这种方法实现三维布局
textfield [i][j].setEditable(false);
textfield [i][j].setVisible(false);
textfield [i][j].setHorizontalAlignment(JTextField.CENTER);
button[i][j].setMargin(new Insets(2,0,2,0)); //设置了边框
button[i][j].addMouseListener(new buttonclick(i,j));
textfield [i][j].addMouseListener(new textfieldclick(i,j));
}
}
}
public void refresh()//重新开局的实现
{
for( int i=0;i<row;i++)
for(int j=0;j<cols;j++)
{
textfield [i][j].setVisible(false);
textfield [i][j].setText("");
button [i][j].setVisible(true);
button[i][j].setText("");
}
flag=false;
laymine();
}
public void ifsuccess()//判断是否扫雷成功
{
int total=0;
for( int i=0;i<row;i++)
for(int j=0;j<cols;j++)
{
if(button [i][j].isVisible()==true)
{
total+=1;
}
}
if(total==minecount)
{
for( int i=0;i<row;i++)
for(int j=0;j<cols;j++)
{
if(button [i][j].isVisible()==true)
{
button[i][j].setText("&");
}
}
flag=true;
}
}
public void laymine()//布雷方法
{
java.util.Random s=new java.util.Random();
for( int i=0;i<minecount;i++)
{
int x =s.nextInt(row);
int y =s.nextInt(cols);
if(textfield[x][y].getText().equals("*"))//有可能重叠
i--;
else
textfield [x][y].setText("*");
}
for( int i=0;i<row;i++)
{
for(int j=0;j<cols;j++)
{
String flag =textfield [i][j].getText();
if(!flag.equals("*"))
{
int value=this.countmine(i,j);
textfield [i][j].setText(""+value);
}
}
}
}
public int countmine(int x,int y)//计算周围的雷数
{
int count =0;
int a=x-1<0?0:x-1;
int b=x+1>row-1?row-1:x+1;
int c=y-1<0?0:y-1;
int d=y+1>cols-1?cols-1:y+1;
for(int i=a;i<=b;i++)
for(int j=c;j<=d;j++)
{
String flag =textfield [i][j].getText();
if(flag.equals("*"))
count+=1;
}
return count;
}
private class buttonclick extends MouseAdapter//按钮的监听器
{
public buttonclick(int a,int b)
{
x=a;
y=b;
}
public void mouseClicked(MouseEvent e)
{
if(flag==true)
return;
if(e.getButton()==MouseEvent.BUTTON1)//左键单击
{
button[x][y].setText("");
button[x][y].setVisible(false);
textfield[x][y].setVisible(true);
if(textfield[x][y].getText().equals("*"))//如果是雷,游戏结束
{
flag=true;
for( int i=0;i<row;i++)
for(int j=0;j<cols;j++)
{
String flag =textfield [i][j].getText();
if(flag.equals("*"))
{
button[i][j].setVisible(false);
textfield[i][j].setVisible(true);
}
}
}
if(textfield[x][y].getText().equals("0"))//如果不是雷且周围没有雷,则打开周围区域
{
textfield[x][y].setText("");
open(x,y);
}
}
if(e.getButton()==MouseEvent.BUTTON3)//右键单击
{
button[x][y].setText("&");
}
ifsuccess();
}
int x;
int y;
}
public void open (int x,int y)//递归打开周围区域
{
int a=x-1<0?0:x-1;
int b=x+1>row-1?row-1:x+1;
int c=y-1<0?0:y-1;
int d=y+1>cols-1?cols-1:y+1;
for(int i=a;i<=b;i++)
for(int j=c;j<=d;j++)
{
if(i==x && j==y)
continue;
if(button[i][j].getText().equals("&"))
continue;
button[i][j].setText("");
button[i][j].setVisible(false);
textfield[i][j].setVisible(true);
if(textfield[i][j].getText().equals("*"))//如果是雷,游戏结束
{
flag=true;
for( int m=0;m<row;m++)
for(int n=0;n<cols;n++)
{
String flag =textfield [m][n].getText();
if(flag.equals("*"))
{
button[m][n].setVisible(false);
textfield[m][n].setVisible(true);
}
}
}
}
for(int i=a;i<=b;i++)
for(int j=c;j<=d;j++)
{
if(textfield[i][j].getText().equals("0"))//递归打开
{
textfield[i][j].setText("");
open(i,j);
}
}
}
private class textfieldclick extends MouseAdapter//文本域监听器
{
public textfieldclick (int a,int b)
{
x=a;
y=b;
}
public void mousePressed(MouseEvent e)
{
if(flag==true)
return;
int test=(MouseEvent.BUTTON1_DOWN_MASK | MouseEvent.BUTTON3_DOWN_MASK);//左右键同时击下
if(!textfield [x][y].getText().equals(""))
{
if ((e.getModifiersEx() & test)==test)
{
int iconcount=0;
int a=x-1<0?0:x-1;
int b=x+1>row-1?row-1:x+1;
int c=y-1<0?0:y-1;
int d=y+1>cols-1?cols-1:y+1;
for(int i=a;i<=b;i++)
for(int j=c;j<=d;j++)
{
if(button[i][j].getText().equals("&"))
{
iconcount+=1;
}
}
if( iconcount==Integer.parseInt(textfield [x][y].getText()))//如果周围雷数和标记的雷数一样,则打开周围非雷的区域
{
open(x,y);
}
}
}
ifsuccess();
}
int x;
int y;
}
private JTextField[][] textfield;
private JButton[][] button ;
private boolean flag;
private int row;
private int cols;
private int minecount;
}
一个方块类Block:封装一个方块的所有属性,包括对旁边八个方块的引用(指针,当然如果用二维数组就可以不要),方块的值(是雷还是数字),对应的图标等等.
一个面板类Panel:里面有整齐布局的很多方块Block.
当然还有对应的监听.
初学java就能写出扫雷,我学了这么久还不会写。