
一.创建窗口1.创建一个类和对象public class Gameui { public static void main(String[] args) { Gameui uinew Gameui(); ui.showUI() } }2.创建showui方法public void showUI() { }3.创建一个窗口对象jf对窗口的属性进行设置Myframe jfnew Myframe();//创建Myframe类的窗口对象 jf jf.setSize(800,800);//设置窗口大小 jf.setLocationRelativeTo(null);//设置窗口居中 jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);//创建关闭方法 jf.setLayout(null);这段代码中布局设为空而Myframe是重写父方法4.加入基本按钮添加startBtn和btnJButton startBtn new JButton(开始游戏); startBtn.setBounds(630, 100, 100, 30); jf.add(startBtn); JButton btn new JButton(悔棋); btn.setBounds(630, 50, 100, 30); jf.add(btn);5.显示窗口jf.setVisible(true);//将窗口显示6.获取窗口的绘图对象Graphics g jf.getGraphics();//获取窗口jf的绘图对象g二.重写父类方法 进行扩展1.重写一个类进行扩展public class Myframe extends JFrame { }2.设置基本变量来确定棋盘大小int X100,Y100,SIZE30,ROW15,COL15;XY为棋盘左上角的坐标值SIZE为每个格子的边长ROW和COL为行列数3.声明方法 调用原本父类方法 绘制窗口public void paint(Graphics gr) { super.paint(gr); }4.绘制棋盘gr.setColor(Color.ORANGE); gr.fillRect(X-SIZE/2,Y-SIZE/2,COL*SIZESIZE,ROW*SIZESIZE); gr.setColor(Color.BLACK); for (int i 0; i ROW ; i) { gr.drawLine(X,Yi*SIZE,XCOL*SIZE,Yi*SIZE); gr.drawLine(Xi*SIZE,Y,Xi*SIZE,YROW*SIZE); }此时我们绘制了一个矩形fillfect用横竖线来绘制棋盘网格。在绘制网格是采用了循环的方法来提高效率。下图为绘制结果三.创建监听器此时需要对鼠标和按钮进行监听要用到MouseListener和ActionListener两类1.创建监听类实现鼠标监听器接口和按钮监听器接口public class Mousel implements MouseListener, ActionListener { }输入基本变量创建对象int X100,Y100,SIZE30,ROW15,COL15;Graphics gr;2.实现方法public interface ActionListener extends EventListener { }此方法用以监控按钮public void mouseClicked(MouseEvent e);{ } public void mousePressed(MouseEvent e);{ } public void mouseReleased(MouseEvent e);{ } public void mouseEntered(MouseEvent e);{ }此方法用来监听鼠标3.在我们创建的类中接入监听在Gameui类中接入鼠标和按钮Mousel mlnew Mousel();//创建对象ml jf.addMouseListener(ml);//给窗口添加监听器ml btn.addActionListener(ml);// 按钮点击事件 startBtn.addActionListener(ml);//将开始游戏的按钮接入监听 ml.grg;//将绘图对象g赋值给监听器ml中的gr jf.mlml;在Myframe类中接入鼠标监听Mousel ml;此代码应该放在方法外四.记录棋子的位置信息在监听器类中在方法体外的设置1.记录下棋数棋子的黑白信息int chessIndex 0; int chessFlag0;2.创建数组来储存棋子位置int[][] carrnew int[ROW1][COL1];创建一个类来构造方法创建对象时使用public class Chess { int r,c,chessFlag; public Chess(int r,int c,int chessFlag){ this.rr; this.cc; this.chessFlagchessFlag; } }在监听器类中方法体里面1.将信息存入数组中在public void mousePressed(MouseEvent e)中需要知道鼠标点击的位置信息xyint xe.getX(); int ye.getY();并将坐标化为网格坐标int c(x-XSIZE/2)/SIZE; int r(y-YSIZE/2)/SIZE;已知r和c的信息就可以把此位置是否有棋的信息存入carr[r][c]chessFlag;同时还可以将此棋位置的信息存入chess中Chess chess new Chess(r,c,chessFlag); chessList[chessIndex]chess; chessIndex;3.按钮开始游戏的判定可以根据chessflag是否为来判断游戏是否开始if(chessFlag0){ JOptionPane.showMessageDialog(null,请先点击开始游戏); return; }在之后将会在按钮类监听来改变chessflag的值4.棋子重复位置的判定在范围外无法下棋判定并进行弹窗提醒if (rROW||cCOL){ JOptionPane.showMessageDialog(null,超出范围无法下棋); return; }对有棋子地方无法下棋的判定if (carr[r][c]!0){ JOptionPane.showMessageDialog(null,该位置有棋子无法下棋); return; }5.棋子的设置棋子有黑白棋可以利用chessflag的值来判断if (chessFlag1){ gr.setColor(Color.BLACK); chessFlag2; }else if (chessFlag2){ gr.setColor(Color.WHITE); chessFlag1; }要保证棋子落在网格交叉点上就需要调整棋子位置圆是以之前的rc为左上角int cxc*SIZEX-SIZE/2; int cyr*SIZEY-SIZE/2; gr.fillOval(cx,cy,SIZE, SIZE);五.对棋盘的刷新在实现悔棋等的功能时需要对棋盘的状态进行改变。可以使用刷新棋盘的操作来实现1.创建方法来实现刷新操作重新绘制表格使用循环操作来绘制出储存在chess中的棋子public void repaint(){ gr.setColor(Color.ORANGE); gr.fillRect(X-SIZE/2,Y-SIZE/2,COL*SIZESIZE,ROW*SIZESIZE); gr.setColor(Color.BLACK); for (int i 0; i ROW ; i) { gr.drawLine(X,Yi*SIZE,XCOL*SIZE,Yi*SIZE); gr.drawLine(Xi*SIZE,Y,Xi*SIZE,YROW*SIZE); } for (int i 0; i chessIndex; i) { Chess chess1 chessList[i]; gr.setColor(chess1.chessFlag1?Color.BLACK:Color.WHITE); gr.fillOval(X chess1.c * SIZE - SIZE / 2, Y chess1.r * SIZE - SIZE / 2, SIZE, SIZE); } }此操作中绘制棋盘和之前操作一致在绘制棋子时使用for循环来遍历chess中储存的棋子信息以此来确定棋子颜色六.接入按钮监听实现游戏操作在ActionListener类中的public void actionPerformed(ActionEvent e)方法中实现1.获取按钮信息创建对象ac来进行判定String ac e.getActionCommand();2.悔棋的实现悔棋需要去掉棋子即将chess中的最后一个信息去掉。注意到我们之前的黑白棋字的判定方法需要将chess flag的值返回之前的状态才能在悔棋后下出正确的棋子颜色最后需要刷新棋盘来更新状态。if(ac.equals(悔棋)){ Chess chess chessList[chessIndex-1]; carr[chess.r][chess.c]0; if (chessFlag1){ chessFlag2; }else{ chessFlag1; } chessIndex--; repaint(); }3.开始游戏和结束游戏的设计可以在点击开始游戏后将开始游戏的按钮变成结束游戏以此来判断游戏是否进行。在点击开始游戏后需要对chessflagchessIndexcarr的状态进行更新完成所有操作后刷新界面else if(ac.equals(开始游戏)){ chessFlag1; chessIndex0; carrnew int[ROW1][COL1]; repaint(); JButton btn (JButton) e.getSource(); btn.setText(结束对局); btn.setBackground(Color.RED); }else if(ac.equals(结束对局)){ chessFlag0; JButton btn (JButton) e.getSource(); btn.setText(开始游戏); btn.setBackground(Color.GREEN); }七.输赢方法的设计五子棋判断输赢为是否有一方的五颗棋子连成一条线可以将其分为3种判定横竖斜1.创建一个类Winpublic class Win { }2.对输赢进行判断判断时用boolean方法1.横向判断创建一个row方法public static boolean row(int[][] arr, int r, int c) { int count 0; for (int i c - 1; i 0; i--) { if (arr[r][i] arr[r][c]) { count; } else { break; } } for (int i c 1; i arr.length; i) { if (arr[r][i] arr[r][c]) { count; } else { break; } } count; return count 5; }利用循环的方法统计同色棋子的个数最后判断count然后返回值(2).竖向判断public static boolean col(int[][] arr, int r, int c) { int count 0; for (int i r - 1; i 0; i--) { if (arr[i][c] arr[r][c]) { count; } else { break; } } for (int i r 1; i arr.length; i) { if (arr[i][c] arr[r][c]) { count; } else { break; } } count; return count 5; }(3).斜向判断斜向分4个方向使用双重循环来统计棋子个数public static boolean left(int[][] arr, int r, int c) { int count0; for(int ir-1,jc-1;i0j0;i--,j--){ if(arr[i][j]arr[r][c]){ count; }else{ break; } } for(int ir1,jc1;iarr.lengthjarr.length;i,j){ if(arr[i][j]arr[r][c]){ count; }else{ break; } } for(int ir-1,jc1;i0jarr.length;i--,j){ if(arr[i][j]arr[r][c]){ count; }else{ break; } } for(int ir1,jc-1;iarr.lengthj0;i,j--){ if(arr[i][j]arr[r][c]){ count; }else{ break; } } count return count 5; } }3.输赢条件判断只用3种方法中1种方法的值为真就可以判为赢static boolean checkWin(int[][] arr, int r, int c) { if (row(arr,r,c)||col(arr,r,c)||left(arr,r,c)) { return true; } return false; }4.输赢棋子的判断在public void mousePressed(MouseEvent e)中调用Win类中的carr来判断棋子if (Win.checkWin(carr,r,c)) { if (carr[r][c] 1) { System.out.println(Black wins!); JOptionPane.showMessageDialog(null, 黑棋获胜); chessFlag1; chessIndex0; carrnew int[ROW1][COL1]; repaint(); } else { System.out.println(White wins!); JOptionPane.showMessageDialog(null, 白棋获胜); chessFlag1; chessIndex0; carrnew int[ROW1][COL1]; repaint(); } }在判断完输赢后将chessIndexcarr恢复初始值刷新后可以继续下棋