Project制作
首先,一个小程序的制作要考虑的首先是程序界面的布局;其次是算法的设计,实现基本功能;然后再添加其他功能。然后就是Bug以及细节的处理;最后就是制作嵌入帮助开发系统。
一:界面布局篇
1:登陆窗口:
使用的布局管理器:GirdBagLayout(网格组布局管理器也可用Box箱式管理器),在这个窗口需要对开始游戏和退出设置鼠标监听,如果开始游戏却没输入名字,会弹出请出入名字,有名字后开始游戏,会将这个名字传递到主窗口中。在监听函数中完成传递。
2:游戏界面:
这个界面需要考虑如何将页面作何很像或是做好。这就需要对java布局的深入理解。
如果认为这是一个边界布局取中间和下面那就错了,这样元件会紧贴边界排布,影响美观。
顶层容器取中:如何在四周留下空隙呢,处理方式有三种,首先使用边界布局管理器,将所有的元件放在中间是必须的,剩下的就是对边界的处理。
方式一:在各个边界添加new JLabel(” ”)中间有空格的JLabel填充一定区域。
方式二:在设置布局的时候,bordelayout(int,int)设置你需要的边界值。这样边界就会有空系。但是,这是在两边界使用的情况下,为此,需要在各个边界添加new JLabel(),或new JLabel(””)中间无空格的空label。这样边界就被名义上的调用而存在,就会满足bordelayout(int,int)两相邻边界的空隙。
方式三:将各个边界使用setpreferredsize()设置固定各个边界的大小。
本人推荐使用第二种,操作简单,也比较精确。
次层容器取中下,在container的容器取中之后,还剩纸牌和三个按钮,纸牌是要统一操作,四个按钮要统一操作。顶层容器的中间添加JPanel容器,JPanel容器再次使用边界布局,只使用中间和下两个部分就可以将两种按钮分开。
三层容器:第三层容器的中间部分可以添加一个网格布局的Jpanel,此JPanel在添加按钮。下部分可以添加一个网格布局的Jpanel或Box布局的Box容器。(此方案采用网格布局)
这样梳理三层容器各个所取的部分和布局方式。就可以实现舒心的布局。
二:算法实现篇
实现游戏算法的大致分为为:随机布局和翻牌判断
随机布局:
① 要将八张牌和一张牌背放到与文件相同的scr文件夹中。用String数组存下地址(编号要顺序排才能用上数组),用imageicon/icon数组顺序存入牌,(16个,背面可单独存)。这样顺序的1234567812345678十六张牌的图标数组就存好了。
② 开始实现随机放牌,建立16位imageicon/icon数组,还要建立一个Integer类型的list集合,用来储存随机图篇对应的数字(个人能力还达不到比较图标,所以把图的比较转化为数%8的比较),将随机过后的牌顺序放入,这是一个抽象的放牌位置。只是按钮数组的执行翻牌的时候对应的调用此图标数组。(按钮数组的初始化是背面图片)。
代码如下:
public void suiji() { boolean b=false; Random r=new Random(); for(int i=0;i<16;i ) { int randomint=r.nextInt(16); for(int j=0;jlisttime=new ArrayList<>(); for(int i=0;i<16;i ) {listtime.add(i);} for(int i=0;i<16;i ) { int randomint=r.nextInt(listtime.size()); int team=listtime.get(randomint); listtime.remove(randomint); random[i]=image[team];list.add(team); } }
(本人采用的是第二这种方案。)
随机布局就完成了,在类中继承Actionlistenner接口,从写监听函数。点击的按钮对应调用seticon()相同位置的随机排序后的icon/imageicon数组,就可以完成了。
翻牌判断:
可以建立一个list1集合装载所有点击的按钮记号。当这个集合的size()为偶数时,执行判断,有两个结果,两张牌相同时,消失,两张牌不同,把图标设置成牌背面图片。这里,牌的判断就用到之前储存随机数字的集合,调用%8看是否相等。
相等的情况:两张牌消失。就用到按钮的一些属性
jbutton[list1.get(list1.size()-2)].setIcon(null); jbutton[list1.get(list1.size()-2)].setContentAreaFilled(false);// 透明 jbutton[list1.get(list1.size()-2)].setBorderPainted(false);// 取消边框 jbutton[list1.get(list1.size()-2)].setFocusPainted(false); // 取消焦点 jbutton[list1.get(list1.size()-2)].setEnabled(false); jbutton[list1.get(list1.size()-1)].setIcon(null); jbutton[list1.get(list1.size()-1)].setContentAreaFilled(false);// 透明 jbutton[list1.get(list1.size()-1)].setBorderPainted(false);// 取消边框 jbutton[list1.get(list1.size()-1)].setFocusPainted(false); // 取消焦点 jbutton[list1.get(list1.size()-2)].setEnabled(false);
当然,要建立一个int类型数字判断是否结束,当消失一张牌这个int类型值就加一。当等于16时结束停止。
两张牌的判断是翻开就进行的,如果不做处理,就会遇到一种情况,相同时,还没看清是否相同就消失了,不相同时,没看见翻得是什么就返回去了。为了避免这种情况,要在里面添加线程,让无论消失还是翻过去都要在0.3秒后执行。
三:其他功能篇
我们添加的其他功能有时间记录,Score记录(i/o),提示功能,背景音乐,结束事件,重新开始。
① 时间记录:我们将时间放在title上显示,用线程控制,start的时候开始,消失16张牌的时候线程结束。
② Score记录:
要实现分数的记录和姓名的记录,需要用到IO流的知识。其中的BufferedReader和BufferedWriter满足此程序的使用要求,建立io()函数,每点击一次score就调用一次。Io()函数中首先建立file文件,判断D盘有没有这个文件,如果没有,就再D盘建立一个tet文件,先读取该文件的内容,按照每行放入String数组中,再弹出窗口显示成绩的排名信息。读取过后再存入放在数组中的内容。(只能先读取在写入,否则文件将会被清空)
如果游戏结束,会自动调用io()储存记录,但是不弹出窗口(可用布尔或其他数值控制)。将数据的数组后一位添加(int)time s 姓名
,这里的排序就需要用到字符串分割,spit(”s”),用前面的有效时间做比较,排序。文件写入的时候写入不超过三个记录。
③ 提示功能:提示功能就是基数次的时候会生效,在前面的list集合中找到数值%8相等并且数值不等的那个数,在对应的按钮上放一个线程让他消失0.3秒在回来,做一个提示作用。
④ 背景音乐和点击铃声:
背景音乐的添加和图标有点类似但是略有不同,背景音乐的实现方法如下:
public AudioClip music;//背景音乐 URL url=Memorize.class.getResource(“music/fade2.wav”);//源 {music=Applet.newAudioClip(url);} music.play();开始
如果循环需要添加:
try { Thread.sleep(40); } catch (InterruptedException e1) { e1.printStackTrace(); } music.loop();
此外,这种循环点击窗体X音乐还会继续播放,需要设置一个关闭的监听时间。在主类中implements actionlisterner。在重载函数中添加
addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent e){ System.exit(0); } });
点击的铃声:
这个程序添加两种点击铃声,一是在按钮上的鼠标点击事件中直接添加铃声1.play();二是在container的容器上添加鼠标点击事件,点击到没有按钮的区域会播放另一种铃声。
⑤ 结束事件:当十六张牌全部消失时,在放了16个按钮的那个面板上使用removeall();函数,再将面板的布局改为绝对布局,使用线程1和算法制作出所有的牌从左往右的飞过效果,顶层容器的背景也闪烁更换,(控制线程慢慢减慢)就可以达到一个由快到慢的过程。线程1结束在执行线程2,name 恭喜你赢了字画从上面移到中间,结束时下方出现重新开始按钮和退出按钮。这里用到线程的加入join()。
⑥ 重新开始,设置restart()函数,将面板再次改为网格布局,重新随机化,将变化的数值再次初始化。
四:bug和细节处理篇
一个小程序就要不产生任何Bug优化所能优化的东西。具体处理有:
1:图标处理:一个小程序的制作就应该完全是自己的元素,JAVA咖啡图标应该抛去
核心就是在设置窗体的时候使用seticonimage()函数。
2:防变形处理:如果你没有使用特殊的布局或者处理时,你的窗体拉伸或导致很丑,很影响美观,你可以使用固定窗口不可拉伸。对应的函数为setResizable(false);
3:位置处理:如果一个小程序点击出现在左上角的边框总有点不好看。可以设置窗体居中,对应的函数为:
setLocationRelativeTo(null)注意:这个函数要在setsize()的后面。因为要设置好大小在整个窗体居中,如果先剧中在设置大小就会导致这个窗体从中心点开始向右下方延伸。
4.按钮控制的严谨性,①在start开始前点图图片不会产生鼠标点击事件②图片被翻开的时候就不会被再次点击,处理不好会导致连续点两次一个图片,图片会自己消失。③当再判断消失或者翻回去的时候要注意让点击事件不在生效,(因为再判断的时候他在线程内你手速太快点击其他按钮,那么操作的最近两个按钮就发生了变化)这个可以使用控制start的那个boolean值进行判断。
5:界面有图形的变换时要用好repaint();函数,即使重绘界面。否则,会出现一些类似“卡主”的界面
(重新开始游戏没使用repaint()函数的结果)
6:如果使用线程计时器,如果单纯的计时倒无所谓,如果这个时间需要使用,需要对线程控制好,控制好休眠前自加还是休眠后自加。
7:线程的生命周期要控制好,设置好约束条件,该结束的时候就结束,避免占用不必要的资源。
8:窗口的退出,disopose()关闭当前窗口,system.exit(0);关闭所有,所以当开始游戏的时候使用dispose();所有的退出使用exit(0);
9:按钮过多的时候写监听就不要用内部类实现,代码会太长。改用接口匿名会简洁的多。
五:帮助系统处理篇
③ 将帮助文件嵌入到GUI程序中。
方法一使用的方法:使用cmd指令打开
代码如下:
public void help() { File file = new File(“doc/help.chm”); Runtime ce=Runtime.getRuntime(); try { ce.exec("cmd /c start " file.getAbsolutePath()); } catch (IOException e) { e.printStackTrace(); } }
这里建立file文件建立相对路径,编译时相对与projiect内部文件夹,导出时相对jar程序。这个,就不用将doc文件放置再固定文件,而是相对放置就可以使用,在编译的过程中,路径名称不能包括空格,否则会识别不出,在运行jar文件时,文件夹名称也不可以改动。(很多程序的内部文件是不可以改动的。)
方法二使用的方法:也可用借助java.awt.desktop打开
代码如下:
public void help() {File file = new File(“doc/help.chm”); try { Desktop.getDesktop().open(file); } catch (IOException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); }}
这种方法可以识别父类路径中有空格的情况,符合更多需要。此程序从方案一优化到方案二。
附上具体代码:初始界面:
import java.awt.Color; import java.awt.Container; import java.awt.FlowLayout; import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTextField; public class chushi extends JFrame implements ActionListener{ static String name=null; //boolean A=false; JButton a=new JButton("开始游戏"); JButton b=new JButton("退 出"); // JButton jb2=new JButton("确定"); JTextField jtex=new JTextField(10); ImageIcon imageicon=new ImageIcon(this.getClass().getResource("image/tubiao.png")); public chushi() { this.setIconImage(imageicon.getImage()); Container c=this.getContentPane(); this.setTitle("memorize game"); this.setSize(450, 250); this.setLocationRelativeTo(null); c.setLayout(new GridBagLayout()); GridBagConstraints d=new GridBagConstraints();//gridbag参数 d.gridx=0;//横方向 d.gridy=0;//纵方向 d.weighty=0.1; d.anchor=d.SOUTH;//应该是对齐方式吧 //d.gridheight=2; JLabel lab=new JLabel("欢迎来到memorize游戏",JLabel.CENTER); lab.setFont(new Font("宋体",1,30)); lab.setForeground(Color.red); c.add(lab,d);d.anchor=d.CENTER; //需要一行 JPanel jp4=new JPanel(); jp4.setLayout(new FlowLayout()); JLabel lab2=new JLabel("请输入你的名字",JLabel.CENTER); lab2.setFont(new Font("宋体",1,16)); /// jtex.setFocusable(false); // 取消焦点 jp4.add(lab2); //wenben jp4.add(jtex); // jp4.add( jb2); d.gridy=1; c.add(jp4,d); d.gridy=2; c.add(a,d); d.gridy=3; c.add(b,d); a.addActionListener(this);b.addActionListener(this);//jb2.addActionListener(this); this.setVisible(true); this.setDefaultCloseOperation(DISPOSE_ON_CLOSE); } public void actionPerformed(ActionEvent e) { // TODO 自动生成的方法存根 if(e.getSource()==a) { if(jtex.getText().equals("")) {JOptionPane.showMessageDialog(this,"请输入姓名!"); jtex.setFocusable(true); } else {new Memorize().name=jtex.getText();dispose();} } if(e.getSource()==b) {System.exit(0);} //if(e.getSource()==jb2) {A=true;name=jtex.getText();} } }
游戏界面:
import java.applet.Applet; import java.applet.AudioClip; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Container; import java.awt.Desktop; import java.awt.FlowLayout; import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.GridLayout; import java.awt.Image; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; 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.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.Random; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTextField; public class Memorize extends JFrame implements ActionListener{ static Thread jishi;int time=-1;//计时 public AudioClip music;//背景音乐 public AudioClip lingsheng,lingsheng2;//点击的铃声 URL url=Memorize.class.getResource("music/fade2.wav");//源 {music=Applet.newAudioClip(url); lingsheng=Applet.newAudioClip(Memorize.class.getResource("music/lingsheng.wav")); lingsheng2=Applet.newAudioClip(Memorize.class.getResource("music/lingsheng2.wav")); } String shijianjilu[][];//io流 String jilu[];//io boolean judgleB=false;//io boolean tanchu=false;// String name=""; static boolean A=false;//控制start static boolean a[]=new boolean[16];//是否应该消失 boolean b[]=new boolean[16];//为true时不可在点击 static int B=0;//计算已经消失的牌数 static Listlist1=new ArrayList<>();//存放了点击按钮的编号 //中间板块所需要的部件 static List list=new ArrayList<>();//存放了随机过后的数字顺序 ImageIcon imageicon=new ImageIcon(this.getClass().getResource("image/beimian.jpg")); Image beimian=imageicon.getImage(); String sousename[]=new String[8];//牌的名字 ImageIcon image[]=new ImageIcon[16];//16张牌 icon也可以 ImageIcon random[]=new ImageIcon[16];//使用过随机数后的图标数组 static JButton jbutton[]=new JButton[16]; //下面板块所需要的部件 JButton start=new JButton("Start"); //start按钮 JButton score=new JButton("Score"); //score按钮 JButton hint=new JButton("hint"); JButton help=new JButton("Help"); //help按钮 JButton restart=new JButton("重新开始"); JButton exit =new JButton("退出"); //中间 //中间上网格 //中间下网格 JPanel jp=new JPanel();JPanel jp2=new JPanel();JPanel jp1=new JPanel(); Container c=this.getContentPane(); /** * 构造函数 **/ public Memorize() { fuzhi();//赋值sousename和image数组 suiji();//赋值random数组 addjubutton(); c.setLayout(new BorderLayout(30,20)); c.setBackground(new Color(250,100,120)); //this.setResizable(false); this.setTitle("memorize game"); this.setIconImage(beimian); this.setSize(800, 900); this.setLocationRelativeTo(null); this.setVisible(true); this.setDefaultCloseOperation(DISPOSE_ON_CLOSE); setResizable(false); jp.setLayout(new BorderLayout(20,20)); jp1.setLayout(new GridLayout(4,4,40,20));//中间 jp2.setLayout(new GridLayout(1,4,20, 0));//下面 c.add(new JLabel(""),BorderLayout.NORTH); c.add(new JLabel(""),BorderLayout.WEST); c.add(new JLabel(""),BorderLayout.EAST); c.add(new JLabel(""),BorderLayout.SOUTH); c.add(jp,BorderLayout.CENTER); jp.setOpaque(false);//设置面板为透明必须有 jp2.setOpaque(false);//jp2(下面设置为透明) jp1.setOpaque(false); jp.add(jp1,BorderLayout.CENTER); jp.add(jp2,BorderLayout.SOUTH); jp2.add(start); jp2.add(score); jp2.add(hint); jp2.add(help); hint.addActionListener(this); help.addActionListener(this); start.addActionListener(this); score.addActionListener(this); restart.addActionListener(this); exit.addActionListener(this); c.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { lingsheng2.play(); } }); addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent e){ System.exit(0); } }); //end(); } /** * 设置标题,用于线程中重复设置个性标题 **/ public void settile() { this.setTitle("memorize game-用时" time "s"); } /** * 计时器,标题的计时和最后的时间结束截取 **/ public void jishi() { jishi=new Thread(new Runnable() { public void run() { while(B<16) { time ; settile(); try {Thread.sleep(1000);}//休眠1S catch(Exception e) {e.printStackTrace();} } } }); jishi.start(); } /** * 使用String的特性赋值icon/imageicon数组 **/ public void fuzhi() { for(int i=0;i<16;i ) { sousename [i%8]="image/" (i%8 1) ".jpg"; //简化代码 image[i]=new ImageIcon(this.getClass().getResource(sousename[i%8])); } } /** * 随机排序位置 **/ public void suiji() { Random r=new Random(); Listlisttime=new ArrayList<>(); for(int i=0;i<16;i ) {listtime.add(i);} for(int i=0;i<16;i ) { int randomint=r.nextInt(listtime.size()); int team=listtime.get(randomint); listtime.remove(randomint); random[i]=image[team];list.add(team); } } /** * 当开始的时候和重新开始的时候需要重新添加按钮 **/ public void addjubutton() { for(int i=0;i<16;i ) { jbutton[i]=new JButton(imageicon); jbutton[i].addActionListener(this); jp1.add(jbutton[i]); } } /** * 结束事件,利用两个线程的动画 **/ public void end() { jp1.removeAll(); jp1.setLayout(null); JLabel jl=new JLabel(name ",恭喜你赢了",JLabel.CENTER); //jl.setForeground(Color.black); jl.setFont(new Font("宋体",0,24)); jp1.add(jl); jp1.setOpaque(false); JLabel label[]=new JLabel[16]; for(int j=0;j<16;j ) {label[j]=new JLabel(image[j]);jp1.add(label[j]);label[j].setBounds(0, 120 j/8*280, 150, 200);} //jp.add(jp1,BorderLayout.CENTER); Random r=new Random();//背景更换 Color color[]={Color.ORANGE,Color.red,Color.yellow,Color.cyan,Color.pink}; Thread d0=new Thread(new Runnable() { int i=0; int count=0; public void run() { while(i<8) {if(count/10%5==0) { int randomint=r.nextInt(5); c.setBackground(color[randomint]);} label[i].setBounds(count, 120, 150, 200); label[i 8].setBounds(count, 400, 150, 200); repaint(); count=count 10; if(count>800) {i ;count=0;} try { Thread.sleep(2 i);} catch(InterruptedException e){System.out.println("当前线程被中断");break;} } } }); Thread d1=new Thread(new Runnable() { int count=0; public void run() { while(count<350) { c.setBackground(new Color(250,100,120)); jl.setBounds(180, count, 400, 100); jl.setFont(new Font("宋体",0,24 count/20)); if(count0==0) { jl.setForeground(color[count/15%5]);} count=count 2; if(count==348) { jp1.add(restart);restart.setBounds(200, 450, 150, 40); jp1.add(exit);exit.setBounds(400, 450, 150, 40); restart.setFont(new Font("宋体",1,22));exit.setFont(new Font("宋体",1,22));} try {Thread.sleep(10);d0.join();} catch(InterruptedException e){System.out.println("当前线程被中断");break;} } }}); d0.start();d1.start(); setVisible(true); } /** * 储存成绩和姓名的函数 **/ public void io()//结束时调用 { //String jilu[]=new String[4]; shijianjilu=new String[4][];//io流 jilu=new String[4]; int geshu=0; File file=new File("word.txt"); if(!file.exists()) {try { file.createNewFile();} catch (IOException e) { // TODO 自动生成的 catch 块 e.printStackTrace();}} try {//先读取 FileReader fi=new FileReader(file); BufferedReader bffi=new BufferedReader(fi); String s=null;int exam=0; while((s=bffi.readLine())!=null) { jilu[exam ]=s; //System.out.println(s); } if(B==16&&judgleB==false) { jilu[exam]=time "s" "姓名:" name;exam ;judgleB=true;} geshu=exam; if(exam==0&&tanchu) {tanchu=false; JOptionPane.showMessageDialog(this, "you will be the NO.1!"); } if(exam==1&&tanchu) { tanchu=false;JOptionPane.showMessageDialog(this,"top1玩家用时:" jilu[0]); } for(int j=0;j Integer.parseInt(shijianjilu[1][0])) { String temp=jilu[0];jilu[0]=jilu[1];jilu[1]=temp; }if(tanchu) {tanchu=false;JOptionPane.showMessageDialog(this,"top1玩家用时:" jilu[0] "\ntop2玩家用时:" jilu[1]);} } if(exam==3) {//paixu if(Integer.parseInt(shijianjilu[1][0])> Integer.parseInt(shijianjilu[2][0])) { String temp=jilu[1];jilu[1]=jilu[2];jilu[2]=temp; if(Integer.parseInt(shijianjilu[0][0])> Integer.parseInt(shijianjilu[2][0])) { String temp2=jilu[0];jilu[0]=jilu[1];jilu[1]=temp2; } if(tanchu) {tanchu=false;JOptionPane.showMessageDialog(this,"top1玩家用时:" jilu[0] "\ntop2玩家用时:" jilu[1]);} } } bffi.close(); fi.close(); } catch (Exception e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } if(geshu!=0) { try {FileWriter writer=new FileWriter(file); BufferedWriter bfwriter=new BufferedWriter(writer); for(int i=0;i<2;i ) { bfwriter.write(jilu[i]); bfwriter.newLine(); // System.out.println(jilu[i]); } bfwriter.close(); writer.close(); } catch(Exception e) {e.printStackTrace();} }} /** * 判断函数 * 用于判断是该消失还是翻回去 * 判断是否结束 **/ public void judgle() { if(list1.size()%2==0) //最后那组数据用偶数判断 { A=false; Thread d1=new Thread(new Runnable() { public void run() { int count=0; while(count<3) { if(count==1&&list.get(list1.get(list1.size()-1))%8==list.get(list1.get(list1.size()-2))%8) { jbutton[list1.get(list1.size()-1)].setIcon(null); jbutton[list1.get(list1.size()-1)].setContentAreaFilled(false);// 透明 jbutton[list1.get(list1.size()-1)].setBorderPainted(false);// 取消边框 jbutton[list1.get(list1.size()-1)].setFocusPainted(false); // 取消焦点 jbutton[list1.get(list1.size()-1)].setEnabled(false); jbutton[list1.get(list1.size()-2)].setIcon(null); jbutton[list1.get(list1.size()-2)].setContentAreaFilled(false);// 透明 jbutton[list1.get(list1.size()-2)].setBorderPainted(false);// 取消边框 jbutton[list1.get(list1.size()-2)].setFocusPainted(false); // 取消焦点 jbutton[list1.get(list1.size()-2)].setEnabled(false); a[list1.get(list1.size()-2)]=true;B ; a[list1.get(list1.size()-1)]=true;B ; // listhelp.remove(list1.get(list1.size()-2)); // listhelp.remove(list1.get(list1.size()-1)); A=true; } if(count==1&&list.get(list1.get(list1.size()-1))%8!=list.get(list1.get(list1.size()-2))%8) { if(a[list1.get(list1.size()-2)]==false) jbutton[list1.get(list1.size()-1)].setIcon(imageicon); b[list1.get(list1.size()-1)]=false; jbutton[list1.get(list1.size()-2)].setIcon(imageicon);b[list1.get(list1.size()-2)]=false; A=true; } if(count==2) { if(B==16) {io();end();} } count ; try {Thread.sleep(300);} catch(InterruptedException e){System.out.println("当前线程被中断");} } } }); d1.start(); } } /** * 提示功能 * 点击为奇数时可以提示另一张牌的位置。 **/ public void hint() { if(list1.size()%2==1) { for(int i=0;i();//存放了点击按钮的编号 list=new ArrayList<>(); jp1.removeAll(); jp1.setLayout(new GridLayout(4,4,40,20));//中间 io(); suiji(); addjubutton(); repaint(); setVisible(true); } /** * 重写的鼠标监听函数 **/ public void actionPerformed(ActionEvent e) { // TODO 自动生成的方法存根 lingsheng.play(); if(e.getSource()==hint) { hint(); } if(e.getSource()==help) { help(); } if(e.getSource()==start) {if(!A){A=true;music.play();try { Thread.sleep(40); } catch (InterruptedException e1) { //TODO 自动生成的 catch 块 e1.printStackTrace(); } music.loop(); jishi(); } } if(e.getSource()==score) {tanchu=true;io();}//位置放错会导致第一次点击不出现 if(A) //数组监听 {for(int i=0;i<16;i ) { if(e.getSource()==jbutton[i]) { if(b[i]==false) { jbutton[i].setIcon(random[i]);list1.add(i); judgle(); b[i]=true; } }} } if(e.getSource()==restart) {restart();} if(e.getSource()==exit) {System.exit(0);} } public static void main(String[] args) { chushi kaishi=new chushi(); //执行开始界面 }}