1.用一个状态变量有时可以表示2个状态
? 比如color={0,1,2}? color=0 表示没有设置颜色,也表示没有棋子
?????????????????????????????? color=1 表示设置棋子为黑色,表示有棋子
???????????????????????????????color=2 表示设置棋子为白色,表示有棋子
?
2.边界判断一定要考虑清楚
??? 比如绘制x行,y列的棋盘,那么每行棋子数目是x+1,每列棋子数目是y+1,极容易出错
?
3.悔棋,下子之后都要用repaint()方法重绘界面,来显示相应的变化
?
4.计算鼠标点击处对应的格子的数组下标,+d/2的目的就是为了四舍五入
?????? 公式 x=(Math.abs(x1-50)+d/2)/d
?
5.用一个状态变量f来表示是否可以下子,胜负结果出来后,f=false
?
6.源代码如下:共3个class文件
6.1Main
package s1222五子棋; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.border.EmptyBorder; // public class Main extends JFrame { int FrameXLength=700,FrameYLength=700; //设置棋盘大小 MyMouseListener l=new MyMouseListener(); //创建鼠标事件监听对象 static public int color[][]=new int[Chess.hang+1][Chess.lie+1]; //记录每个格子的棋子颜色,0表示没有棋子,1表示黑棋,2表示白棋 //1.注意,画n条直线,n条竖线,那么每行每列都有n+1个棋子,所以数组长度要开n+1个!!!! //2.注意,color这一个状态变量就可以表示2中状态,棋子颜色和是否有棋子,color==0就表示没有棋子,我把2个状态变量压缩为1个了 Main() //构造方法直接画出界面 { //设置初始各个格子状态为0,表示没有棋子,防止在同一个格子落子;颜色状态为0,表示没有设置颜色****************** for(int i=0;i<=Chess.hang;i++) for(int j=0;j<=Chess.lie;j++) {color[i][j]=0;} //设置初始各个格子状态为0,表示没有棋子,防止在同一个格子落子;颜色状态为0,表示没有设置颜色****************** //设置窗体属性************************************************ this.setTitle("五子棋"); this.setDefaultCloseOperation(3); this.setSize(FrameXLength,FrameYLength); this.setResizable(true); this.setLocationRelativeTo(null); this.setLayout(new BorderLayout()); //设置窗体属性************************************************ //设置左边的面板********************************************** JPanel west=new JPanel(); west.setBackground(Color.GRAY); west.setPreferredSize(new Dimension(100,0)); west.setLayout(null); //设置左边的面板********************************************** //创建按钮******************************************* EmptyBorder emp=new EmptyBorder(0,0,0,0); JButton j1=new JButton("开始"); //创建按钮 j1.setBorder(emp); //设置边框 j1.setBounds(10, 100, 80, 40); //设置按钮的位置 j1.setBackground(Color.CYAN); //设置按钮底色 j1.addActionListener(l); //添加事件监听对象 west.add(j1); //将按钮添加到窗体中 JButton j2=new JButton("认输"); j2.setBorder(emp); j2.setActionCommand("认输"); j2.setBounds(10, 150, 80, 40); j2.setBackground(Color.CYAN); j2.addActionListener(l); //添加事件监听对象 west.add(j2); JButton j3=new JButton("悔棋"); j3.setBorder(emp); j3.setActionCommand("悔棋"); j3.setBounds(10, 200, 80, 40); j3.setBackground(Color.CYAN); j3.addActionListener(l); //添加事件监听对象 west.add(j3); //创建按钮******************************************* //设置绘画的面板*********************************************************************** //绘制界面的代码还要仔细看看 JPanel drawpanel =new JPanel() { public void paint(Graphics g) //重写JPanel中的方法 { super.paint(g); int x=Chess.x; //棋盘起始x坐标 int y=Chess.y; //棋盘起始y坐标 int d=Chess.d; //棋盘间距 int hang=Chess.hang;//行数,注意每行棋子最多有hang+1个,所以数组的下标最大值是hang int lie=Chess.lie; //列数,注意每列棋子最多有hang+1个,所以数组的下标最大值是hang //绘制hang+1条横线,lie+1条竖线,总共hang*lie个格子***************** for(int i=0;i<=hang;i++) {g.drawLine(x, y+d*i,x+lie*d,y+d*i); //绘制hang+1条横线 g.drawLine(x+d*i,y,x+d*i,y+d*hang);}//绘制lie+1条横线 //绘制hang+1条横线,lie+1条竖线,总共hang*lie个格子***************** for(int i=0;i<MyMouseListener.list.size();i++) MyMouseListener.list.get(i).draw(g); } }; drawpanel.setBackground(Color.lightGray); drawpanel.addMouseListener(l); //设置绘画的面板*********************************************************************** //设置中间的面板********************************************** JPanel center=new JPanel(); center.setBackground(Color.WHITE); center.setLayout(new BorderLayout()); center.add(drawpanel,BorderLayout.CENTER); //设置中间的面板********************************************** //给窗体添加面板,传递画笔************************************* this.add(center,BorderLayout.CENTER); this.add(west,BorderLayout.WEST); this.setVisible(true); Graphics g=drawpanel.getGraphics(); l.setGraphics(g,drawpanel); //给窗体添加面板,传递画笔************************************* } public static void main(String[] args) { Main t1=new Main(); } }
?6.2Mymouselistener
package s1222五子棋; import java.awt.Color; import java.awt.Graphics; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; import javax.swing.JOptionPane; import javax.swing.JPanel; //extends MouseAdapter 因为mouselistener中不是所有方法都要用到,所以用extends比较好 public class MyMouseListener extends MouseAdapter implements ActionListener { int x1,y1; //棋子的绝对坐标值 Graphics g; //声明画笔 int x,y; //棋子的格子下标 int d=Chess.d; //棋盘格子间距 JPanel drawpanel=null; //接收绘画面板对象 Boolean black=true,f=true; //black用来设置棋子颜色,f为false就不能再下棋子 public static ArrayList<Chess> list=new ArrayList<Chess>(); //用一个队列来保存棋子信息 public void setGraphics(Graphics g,JPanel drawpanel) {this.g=g; this.drawpanel=drawpanel;} public void actionPerformed(ActionEvent e) { if(e.getActionCommand().equals("开始")) { f=true; while(list.size()>0) { Main.color[list.get(list.size()-1).qizix][list.get(list.size()-1).qiziy]=0; //设置格子中棋子颜色为没有设置 list.remove(list.size()-1); //队列中删掉棋子 } black=true; drawpanel.repaint(); } //重绘 if(e.getActionCommand().equals("认输")&&f) { f=false; if(black==true) JOptionPane.showMessageDialog(null,"黑方认输,白方胜利"); else JOptionPane.showMessageDialog(null,"白方认输,黑方胜利");} if(e.getActionCommand().equals("悔棋")&&f) //悔棋只能在事件里面更改,不能到mousePressed中更改,&&f用的好,借鉴别人的 { if(list.size()>0) { int i=list.get(list.size()-1).qizix; //得到最后落子的x坐标 int j=list.get(list.size()-1).qiziy; //得到最后落子的y坐标 Main.color[i][j]=0; //颜色状态变量设置为0 black=!black; //因为悔棋,所以要改变棋子颜色状态变量 list.remove(list.size()-1); //悔棋,悔棋之后要重绘,界面才会显示出区别来 drawpanel.repaint(); //重绘,调用的是重写过的repaint方法 // for(int i=0;i<MyMouseListener.list.size();i++) // 重新绘制不能加在这里,一定要加在主函数 // { MyMouseListener.list.get(i).draw(g); } } else return; } } public void mousePressed(MouseEvent e) { if(f) { x1=e.getX(); y1=e.getY(); x=(Math.abs(x1-50)+d/2)/d;//计算鼠标点击处对应的格子的横坐标是第几格,这个公式很关键,隐含了四舍五入 y=(Math.abs(y1-50)+d/2)/d;//计算鼠标点击处对应的格子的纵坐标是第几格,这个公式很关键,隐含了四舍五入 if(x>=0&&y>=0&&x<=(Chess.hang)&&y<=(Chess.lie)&&Main.color[x][y]==0) //棋盘边界判断条件 { String s; if(black) //判断是黑棋还是白棋 { s="黑棋"; g.setColor(Color.BLACK);//设置画笔颜色 black=false; //black=false表示这一次下的是黑棋,改变状态变量的值,下一次就下白棋 Main.color[x][y]=1; } else { s="白棋"; g.setColor(Color.WHITE);//设置画笔颜色 black=true; //black=true表示这一次下的是白棋,改变状态变量的值,下一次就下黑棋 Main.color[x][y]=2; } Chess chess=new Chess(50+x*d-d/2,50+y*d-d/2,Main.color[x][y],x,y);//创建一个棋子对象,保存信息 list.add(chess);System.out.println("list.size="+list.size()); //将棋子添加到队列中 g.fillOval(50+x*d-d/2, 50+y*d-d/2, d, d); //画棋子 this.winner(x, y,s); //判断胜负 } else if(Main.color[x][y]!=0) //如果点击处已经有棋子了 { JOptionPane.showMessageDialog(null,"无效落子"); for(int i=0;i<list.size();i++) list.get(i).draw(g); //弹出信息框之后会重画,所以要这2行代码。 } }} public void winner(int x,int y,String s) { int x11=x-4,y11=y-4,x22=x+4,y22=y+4; int count1=0,count2=0,count3=0,count4=0; String t=s; for(int i=x11;i<=x22;i++)//判断从左到右,从上到下斜向是否胜利 { if(i>=0&&y11>=0&&i<=Chess.hang&&y11<=Chess.lie) { if(Main.color[i][y11++]==list.get(list.size()-1).color) count1++; else count1=0;//颜色相同计数+1 if(count1==5) {JOptionPane.showMessageDialog(null, t+"Win");f=false;} //连续五个相同,则胜利 } else{y11++;} } for(int i=x11;i<=x22;i++)//判断从左到右,从下到上斜向是否胜利 { if(i>=0&&y22>=0&&i<=Chess.hang&&y22<=Chess.lie) { if(Main.color[i][y22--]==list.get(list.size()-1).color) count2++; else count2=0; //颜色相同计数+1 if(count2==5) {JOptionPane.showMessageDialog(null, t+"Win");f=false;} //连续五个相同,则胜利 } else{y22--;} } for(int i=x11;i<=x22;i++)//判断从左到右,横向是否胜利 { if(i>=0&&i<=Chess.hang) { if(Main.color[i][y]==list.get(list.size()-1).color) count3++; else count3=0; //颜色相同计数+1 if(count3==5) {JOptionPane.showMessageDialog(null, t+"Win");f=false;} //连续五个相同,则胜利 } } for(int i=y11;i<=y22;i++)//判断从左到右,横向是否胜利 { if(i>=0&&i<=Chess.lie) { if(Main.color[x][i]==list.get(list.size()-1).color) count4++; else count4=0; //颜色相同计数+1 if(count4==5) {JOptionPane.showMessageDialog(null, t+"Win");f=false;} //连续五个相同,则胜利 } } } }
?6.3chess? 用来设置棋盘属性,
package s1222五子棋; import java.awt.Color; import java.awt.Graphics; public class Chess { public static final int hang=12; //棋盘行数 public static final int lie=12; //棋盘列数 public static final int x=50; //棋盘左上角x坐标 public static final int y=50; //棋盘左上角y坐标 public static final int d=40; //棋盘格子间距 int x1; //棋子的绝对坐标 int y1; //棋子的绝对坐标 int color; //0表示未设置颜色,1表示黑色,2表示白色 int qizix; //棋子的格子下标 int qiziy; //棋子的格子下标 public Chess(int x,int y,int color,int qizix,int qiziy) //构造方法 { this.x1=x; this.y1=y; this.color=color; this.qizix=qizix; this.qiziy=qiziy; } public void draw(Graphics g) //绘图 { if(color==1) g.setColor(Color.BLACK); if(color==2) g.setColor(Color.WHITE); g.fillOval(x1, y1, d, d); } }
?