Java 五子棋(三)轮流下棋、悔棋、判断输赢

五子棋

  • 功能分析
    • 轮流下棋
    • 悔棋
  • 功能实现
    • 界面绘制与更新
    • 悔棋
  • Code
    • Fivechess
    • FivechessLisenter
    • Fiveface
    • Fivepreserve
    • Fiveshape
    • FivechessLisenter
    • FivechessUI
    • IsWin

功能分析

轮流下棋

  • 下棋:
    - 将棋子放置在棋盘线上的交叉点上
    - 轮流下棋

悔棋

功能实现

界面绘制与更新

  • 界面绘制:
    - 可用JPanel将其分为下棋区域和按钮区域
    - 重写paint方法,使得每次拖动棋盘都会更新一次

悔棋

  • 悔棋:
    - 从最后下的棋子开始撤销

Code

Fivechess

  • 设置窗体大小、名称、退出进程、可视化
    public void showUI(){
        JFrame jf=new JFrame();
        jf.setTitle("五子棋");
        jf.setSize(800,800);   jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  • 创建面板对象,设置布局的位置、颜色
JPanel jbupl=new JPanel();
        jf.add(jbupl,BorderLayout.EAST);
        Fiveshape fiveshape=new Fiveshape();
        jf.add(fiveshape,BorderLayout.CENTER);
        fiveshape.setBackground(Color.WHITE);   
  • 创建全局变量监听器对象
 FivechessLisenter fivechessLisenter=new FivechessLisenter();
  • 设置一个初始化按钮面板的方法,给按钮面板设置大小、颜色、排布的位置、按钮名
  public void initjbu(ActionListener actionListener,JPanel jPanel){
        Dimension dimension=new Dimension(125,300);
        jPanel.setLayout(new BorderLayout());
        JPanel njp=new JPanel();
        JPanel sjp=new JPanel();
        njp.setBackground(Color.PINK);
        sjp.setBackground(Color.orange);
        njp.setPreferredSize(dimension);
        sjp.setPreferredSize(dimension);
        jPanel.add(njp,BorderLayout.NORTH);
        jPanel.add(sjp,BorderLayout.SOUTH);
        Dimension dimension1=new Dimension(120,45);
        String name[]={"开始游戏","悔棋","暂停","结束游戏"};
        String name1[]={"白棋","黑棋"};
        for (int i = 0; i < name.length; i++) {            jbuchess(fivechessLisenter,dimension1,Color.pink,name[i],njp );
        }
        for (int i = 0; i < name1.length; i++) {            jbuchess(fivechessLisenter,dimension1,Color.ORANGE,name1[i],sjp );
        }
    }
    public void jbuchess(ActionListener actionListener,Dimension dimension,Color color,String string,JPanel jPanel){
        JButton jButton=new JButton(string);
        jButton.addActionListener(actionListener);
        jButton.setBackground(color);
        jButton.setPreferredSize(dimension  );
        jPanel.add(jButton);
    }
  • 将初始化的按钮面板方法放在可视化之前
   initjbu(fivechessLisenter,jbupl);
        jf.setVisible(true); 

FivechessLisenter

  • 监听器继承鼠标监听器、动作监听器,在属性栏设置:重绘棋子类对象、画笔对象、二维数组范围、创建一个公共类对象、int 对象初始化的值
public class FivechessLisenter implements MouseListener, ActionListener,Fiveface {
    Graphics g;
    Fiveshape fiveshape;
    int [][]chessArr=new int[L+1][R+1];
    ArrayListfivepreserveArrayList=new ArrayList<>();
    int count=1;
  • 在按下的方法中,直接运用,判断为“开始游戏”时开始下棋,执行封装的判断输赢的方法
 public void mousePressed(MouseEvent e) {
        int x = e.getX();
        int y = e.getY();
        if(str.equals("开始游戏")){
            chess(x, y);
            IsWin.isWin(chessArr,ChessL,ChessR,chessFlag);
            chessFlag=3-chessFlag;
        }
    }
  • 将轮流下棋设置成一个封装方法,设置x、y矫正的位置及还原的坐标点,
  • 判断数组长度等于0时,在判断矫正点是否为1,为1时话黑棋数组对象chessArr的长度赋值给int 对象,创建一个棋子类对象(矫正位置及判定条件),将保存的棋子类对象调用添加到公共类中
  • 画3D棋子、画完黑棋接着画白棋,白棋方法与黑棋方法一致
    -可将上述判断条件
 public void chess(int x,int y){
    int ChessL = (x - X + Size / 2) / Size;
    int ChessR = (y - Y + Size / 2) / Size;
    int ChessX = ChessL * Size + X - Size / 2;
    int ChessY = ChessR * Size + Y - Size / 2;
    if(chessArr[ChessL][ChessR]==0){
        if (chessFlag==1) {
            chessArr[ChessL][ChessR]=chessFlag;
            Fivepreserve black=new Fivepreserve(ChessR,ChessL,chessFlag);
            fivepreserveArrayList.add(black);
            for (int i = 0; i < Size; i++) {
                g.setColor(new Color(i * 3, i * 3, i * 3));
                g.fillOval(ChessX + i / 2, ChessY + i / 2, Size - i, Size - i);
                chessFlag = 2;
            }
        } else if (chessFlag == 2) {
            chessArr[ChessL][ChessR] = chessFlag;
            Fivepreserve white = new Fivepreserve(ChessR, ChessL, chessFlag);
            fivepreserveArrayList.add(white);
            for (int i = 0; i < Size; i++) {
                g.setColor(new Color(i + 205, i + 205, i + 205));
                g.fillOval(ChessX + i / 2, ChessY + i / 2, Size - i, Size - i);
                chessFlag = 1;
            }
        }
    }else {
        return;
    }
}

Fiveface

  • 单独创建一个接口,写其需要用到的常量属性,方便后面被用到
  int X=100;
    int Y=100;
    int L=10;
    int R=10;
    int Size=50;

Fivepreserve

  • 创建一个保存棋子的类,写其属性及保存的方法,当前类调用申明的变量 赋值给参数(为了保存)
public class Fivepreserve {
   int chessR;
   int chessL;
   int chessNum;
   int chessFlag;
    public  Fivepreserve( int chessR,int chessL,int chessNum,int chessFlag){
  
       this.chessR=chessR;
       this.chessL=chessL;
       this.chessNum=chessNum;
       this.chessFlag=chessFlag;
   }
}

Fiveshape

  • 创建一个重绘棋子的类,继承JPanel、接口,申明一个二位数组对象,继承JPanel中的paint重绘方法,画棋盘线,画棋子
public class Fiveshape extends JPanel implements Fiveface{
    int [][]chessArr;
    public void paint(Graphics g) {
        super.paint(g);
        drawline(g);
        drawchess(g);
        System.out.println("A");
    }
  • 设置画直线的封装方法
 public  void drawline(Graphics g){
        for (int i = 0; i <11 ; i++) {
            g.drawLine(X,Y+i*Size,X+Size*L,Y+i*Size);
            g.drawLine(X+i*Size,Y+Size*L,X+i*Size,Y);
        }
    }
  • 设置画棋子的封装方法,for循环二维数组中的一位数组的长度,再for循环一维数组中的长度,申明一个变量赋值给二维数组对象,判定下白棋还是黑棋
 public void drawchess(Graphics g){
        for (int i = 0; i 

FivechessLisenter

  • 在监听器中设置一个悔棋的方法,申明一个int对象赋值给公共类保存棋子类对象调用得到的
  • 申明一个保存类对象赋值给公共类对象调用得到值,且在此基础上逐一递减1
  • 数组对象长度赋值为0,判断size-1不为0时,执行size-1,否则无法悔棋,重绘
 public void huiqi() {
        int size = fivepreserveArrayList.size();
        Fivepreserve fivepreserve = fivepreserveArrayList.get(size - 1);
        chessArr[fivepreserve.chessL][fivepreserve.chessR] = 0;
        if (size - 1 != 0) {
            fivepreserveArrayList.remove(size - 1);
        } else {
            System.out.println("无法悔棋");
        }
        chessFlag = fivepreserve.chessFlag;
        fiveshape.repaint();
    }
  • 动作监听器方法中判断是否为“悔棋”,为“悔棋”执行悔棋的封装方法
 public void actionPerformed(ActionEvent e) {
        String str=e.getActionCommand();
       if( str.equals("悔棋")){
               huiqi();
       }
    }

FivechessUI

  • 申明画笔对象赋值为重绘的棋子类对象调用得到的画笔对象,将监听器对象添加到重绘棋子类对象中
  • 监听器对象调用画笔对象、重绘的棋子类对象,赋值给申明的画笔对象、重绘的棋子类对象,重绘的棋子类对象调用数组对象赋值给监听器调用数组对象
 Graphics g=fiveshape.getGraphics();
        fiveshape.addMouseListener(fivechessLisenter);
        fivechessLisenter.g=g;
        fivechessLisenter.fiveshape=fiveshape;
        fiveshape.chessArr= fivechessLisenter.chessArr;

IsWin

  • while:多次循环结构,while计算的的表达式必须是boolean值,直至ture(执行{}中所有的代码)/false(否则false),用while是为了多次执行
  • 写四个方位的判断输赢,分别为横向、纵向、以及两个斜方向的
public class IsWin {
//(横向)
    static int   winL_R(int[][] chessArr, int m, int n) {
        int count = 0;
        for (int i = n; i < chessArr.length-1; i++) {
            if (chessArr[m][n] == chessArr[m][i]) {
                count++;
            } else {
                break;
            }
        }
        for (int i = n-1; i > 0; i--) {
            if (chessArr[m][n] == chessArr[m][i]) {
                count++;
            } else {
                break;
            }
        }
//        System.out.println("count:"+count);
        return count;
    }
    //纵向
    static int   winU_D(int[][] chessArr, int m, int n) {
        int count = 0;
        for (int i = m; i < chessArr.length-1; i++) {
            if (chessArr[m][n] == chessArr[i][n]) {
                count++;
            } else {
                break;
            }
        }
        for (int i = m-1; i >0; i--) {            if (chessArr[m][n] == chessArr[i ][n]) {
                count++;
            } else {
                break;
            }
        }
//        System.out.println("count:"+count);
        return count;
    }
    // 斜方向(左下右上)的方向
    static int   winLD_RU(int[][] chessArr, int m, int n) {
        int count = 0;
        int i = m;
        int j = n;
        while (i >0 && j < chessArr.length-1) {
            if (chessArr[m][n] == chessArr[i ][j ]) {
                count++;
                i--;
                j++;
            } else {
                break;
            }
        }
        i = m;
        j = n;
        while (i < chessArr.length-1 && j >0) {
            if (chessArr[m][n] == chessArr[i+1 ][j-1 ]) {
                count++;
                i++;
                j--;
            } else {
                break;
            }
        }
        System.out.println("count:"+count);
        return count;
    }
    // 斜方向(左上右下)的方向
    static int winLU_RD(int[][] chessArr, int m, int n) {
        int count = 0;
        int i = m;
        int j = n;
        while (i < chessArr.length-1 && j < chessArr.length-1) {
            if (chessArr[m][n] == chessArr[i+1][j+1]) {
                count++;
                i++;
                j++;
            } else {
                break;
            }
        }
        i = m;
        j = n;

        while (i > 0 && j > 0) {
            if (chessArr[m][n] == chessArr[i ][j ]) {
                count++;
                i--;
                j--;
            } else {
                break;
            }
        }
        System.out.println("count:"+count);
        return count;
    }
    //判断输赢的静态方法
    static  void isWin(int[][] chessarr,int m,int n,int chessFlag) {
        System.out.println("chessFlag"+chessFlag);
            if(winL_R ( chessarr,m,n)>=5|winU_D ( chessarr,m,n)>=5|winLD_RU( chessarr,m,n)>=5|winLU_RD( chessarr,m,n)>=5){
                if(chessFlag==1){
                    System.out.println( "黑棋赢了");
                }else if(chessFlag==2){
                    System.out.println( "白棋赢了");
                }
            }else {
                return;
            }
    }
}

你可能感兴趣的:(笔记,java,开发语言,后端)