java小程序:五子棋对战的实现

第一部分:

第一个类:

package gobang227;//这是包名,copy的同学记得修改!!!!

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;

import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;

//定义棋盘类让其继承面板类,原因为之后要重写棋盘面板类的paint方法,将棋盘面板重置
public class GoBangMain extends JPanel implements GoBangDate {
    // 定义初始化界面函数
    public void initUI() {
        // 实例化界面对象jr,设置界面标题,大小,关闭,居中,改变大小选项不可选
        JFrame jf = new JFrame();
        jf.setTitle("五子棋对战");
        jf.setSize(760, 630);
        jf.setDefaultCloseOperation(3);
        jf.setLocationRelativeTo(null);
        jf.setResizable(false);
        // 整体布局为边框布局,JFrame默认布局为边框布局
        jf.setLayout(new BorderLayout());

        // 添加棋盘面板,添加到边框布局的中部
        jf.add(this, BorderLayout.CENTER);
        this.setBackground(Color.gray);

        // 功能面板,默认为流式布局
        JPanel panel = new JPanel();
        panel.setPreferredSize(new Dimension(150, 0));
        // 添加空白区域(美观的要求)
        JLabel label = new JLabel();
        label.setPreferredSize(new Dimension(140, 120));
        panel.add(label);
        // 添加功能面板
        jf.add(panel, BorderLayout.EAST);
        // 添加功能按钮
        JButton bu1 = new JButton("开始新游戏");
        JButton bu2 = new JButton("悔棋");
        JButton bu3 = new JButton("认输");
        bu1.setPreferredSize(new Dimension(140, 60));
        bu2.setPreferredSize(new Dimension(140, 60));
        bu3.setPreferredSize(new Dimension(140, 60));
        panel.add(bu1);
        panel.add(bu2);
        panel.add(bu3);

        JRadioButton jr1 = new JRadioButton("人人对战");
        JRadioButton jr2 = new JRadioButton("人机对战");
        jr1.setPreferredSize(new Dimension(80, 40));
        jr2.setPreferredSize(new Dimension(80, 40));
        // 将jr1和jr2分组,保证每次只能选中一个按钮
        ButtonGroup bg = new ButtonGroup();
        bg.add(jr1);
        bg.add(jr2);
        // 默认选中为jr1按钮,即人人对战
        jr1.setSelected(true);
        // 把两个按钮添加到功能面板上
        panel.add(jr1);
        panel.add(jr2);
        // 复选框
        JCheckBox jc = new JCheckBox("AI先手");
        jc.setPreferredSize(new Dimension(80, 40));
        panel.add(jc);
        // 可见
        jf.setVisible(true);
        // 实例化画笔对象
        Graphics g = this.getGraphics();
        // 实例化监听接口,并传参,参数为画笔对象
        GoBangListener gl = new GoBangListener(g);
        // 给棋盘面板添加监听方法,监听处理类的对象为gl
        this.addMouseListener(gl);

    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        // 调用棋盘面板初始化的方法,使棋盘面板初始化
        drawChessBorder(g);
    }

    // 定义棋盘面板初始化的方法
    private void drawChessBorder(Graphics g) {
        for (int i = 0; i < ROW; i++)
            g.drawLine(X, Y + i * SIZE, X + (COLUMN - 1) * SIZE, Y + i * SIZE);
        for (int i = 0; i < COLUMN; i++)
            g.drawLine(X + i * SIZE, Y, X + i * SIZE, Y + (ROW - 1) * SIZE);

    }

    public static void main(String[] args) {
        // 实例化棋盘类对象,调用初始化函数
        GoBangMain go = new GoBangMain();
        go.initUI();
    }

}

 

第二个类:

package gobang227;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

public class GoBangListener implements MouseListener, GoBangDate {
    private Graphics g;
    // x,y为坐标值,row,col为棋子的行和列(例如:左上角行列数为1,1)
    private int x, y, row, col;
    // 棋子颜色的标志位,1为黑棋,2为白棋
    private int flag = 1;

    // 构造方法
    public GoBangListener(Graphics g) {
        this.g = g;
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        // 获取点击位置的横纵坐标
        x = e.getX();
        y = e.getY();
      

       // 计算点击位置的行和列,确认棋子把棋子放在相应交叉点

//在这里注意为什么要减去CHESSSIZE / 2,因为画棋子的时候或者说画椭圆的时候调用 fillOval(x, y, CHESSSIZE,     CHESSSIZE)方法,但是在这里参数x,y是以椭圆大小为边框的矩形的左上角,不是大家想象中的圆心!!!!!!
        row = Math.round(y / SIZE);
        System.out.println("这个棋子在第" + row + "行!");
        y = Y - CHESSSIZE / 2 + (row - 1) * SIZE;

        col = Math.round(x / SIZE);
        System.out.println("这个棋子在第" + col + "列!");
        x = X - CHESSSIZE / 2 + (col - 1) * SIZE;

        // 确保点击位置在棋盘上
        if (row <= ROW && col <= COLUMN) {
            // flag=1说明下个棋子是黑棋
            if (flag == 1) {
                g.setColor(Color.black);
                g.fillOval(x, y, CHESSSIZE, CHESSSIZE);
                // 把下个棋子的颜色置为白棋
                flag = 2;
            } else {
                g.setColor(Color.white);
                g.fillOval(x, y, CHESSSIZE, CHESSSIZE);
                flag = 1;
            }
        } else {
            System.out.println("这个位置不在棋盘上");
            System.out.println("这个位置的横坐标为:" + x);
            System.out.println("这个位置的纵坐标为:" + y);

        }
    }

    @Override
    public void mousePressed(MouseEvent e) {

    }

    @Override
    public void mouseReleased(MouseEvent e) {

    }

    @Override
    public void mouseEntered(MouseEvent e) {

    }

    @Override
    public void mouseExited(MouseEvent e) {

    }

}

 


第三个类(这是个接口):

package gobang227;

public interface GoBangDate {
    // 设置棋盘面板的起始坐标
    public int X = 50;
    public int Y = 50;
    // 设置棋盘面板的横线竖线个数
    public int ROW = 15;
    public int COLUMN = 15;
    // 设置棋盘面板的格子大小,SIZE为正方形方格的长宽,CHESSSIZE为棋子的长宽
    public int SIZE = 35;
    public int CHESSSIZE = 25;

 

运行结果:OK我们现在可以画出来一个棋盘啦,也可以进行相应的点击,而且出现棋子的位置都在交叉点上。

那我们还存在什么问题呢?

1.右边的功能按钮功能还没做

2.点击两次同一个位置会造成棋子覆盖(定义一个二维数组来确认交叉点是否已经下过棋子了)

3.重绘的问题(界面最小化一下就什么都没了)

4.不能判断输赢

}java小程序:五子棋对战的实现_第1张图片

 

第二部分:这部分代码用于解决重绘的问题

第一个类:

package gobang228.copy;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;

import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;

//定义棋盘类让其继承面板类,原因为之后要重写棋盘面板类的paint方法,将棋盘面板重置
public class GoBangMain extends JPanel implements GoBangDate {
    // 定义初始化界面函数
    public void initUI() {
        JFrame jf = new JFrame();
        jf.setTitle("五子棋对战");
        jf.setSize(760, 630);
        jf.setDefaultCloseOperation(3);
        jf.setLocationRelativeTo(null);
        jf.setResizable(false);
        // 整体布局为边框布局,JFrame默认布局为边框布局
        jf.setLayout(new BorderLayout());

        // 添加棋盘面板,添加到边框布局的中部
        jf.add(this, BorderLayout.CENTER);
        this.setBackground(Color.gray);

        // 功能面板,默认为流式布局
        JPanel panel = new JPanel();
        panel.setPreferredSize(new Dimension(150, 0));

        JLabel label = new JLabel();
        label.setPreferredSize(new Dimension(140, 120));
        panel.add(label);
        // 添加功能面板
        jf.add(panel, BorderLayout.EAST);
        // 添加功能按钮
        JButton bu1 = new JButton("开始新游戏");
        JButton bu2 = new JButton("悔棋");
        JButton bu3 = new JButton("认输");
        bu1.setPreferredSize(new Dimension(140, 60));
        bu2.setPreferredSize(new Dimension(140, 60));
        bu3.setPreferredSize(new Dimension(140, 60));
        panel.add(bu1);
        panel.add(bu2);
        panel.add(bu3);

        JRadioButton jr1 = new JRadioButton("人人对战");
        JRadioButton jr2 = new JRadioButton("人机对战");
        jr1.setPreferredSize(new Dimension(80, 40));
        jr2.setPreferredSize(new Dimension(80, 40));
        ButtonGroup bg = new ButtonGroup();
        bg.add(jr1);
        bg.add(jr2);
        // 默认选中为jr1按钮,即人人对战
        jr1.setSelected(true);
        panel.add(jr1);
        panel.add(jr2);
        // 复选框
        JCheckBox jc = new JCheckBox("AI先手");
        jc.setPreferredSize(new Dimension(80, 40));
        panel.add(jc);

        jf.setVisible(true);
        // 实例化画笔对象
        Graphics g = this.getGraphics();
        // 实例化监听接口,并传参,参数为画笔对象
        GoBangListener gl = new GoBangListener(g);
        this.addMouseListener(gl);

    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        // 调用棋盘面板初始化的方法,使棋盘面板初始化
        drawChessBorder(g);
        // 棋盘面板的重绘
        for (int r = 0; r < FLAG.length; r++) {
            for (int c = 0; c < FLAG[r].length; c++) {
                if (FLAG[r][c] != 0) {
                    int x = X + c * SIZE - CHESSSIZE / 2;
                    int y = Y + r * SIZE - CHESSSIZE / 2;
                    if (FLAG[r][c] == 1) {
                        g.setColor(Color.BLACK);
                    } else {
                        g.setColor(Color.white);
                    }
                    g.fillOval(x, y, CHESSSIZE, CHESSSIZE);

                }

            }
        }

    }

    // 定义棋盘面板初始化的方法
    private void drawChessBorder(Graphics g) {
        for (int i = 0; i < ROW; i++)
            g.drawLine(X, Y + i * SIZE, X + (COLUMN - 1) * SIZE, Y + i * SIZE);
        for (int i = 0; i < COLUMN; i++)
            g.drawLine(X + i * SIZE, Y, X + i * SIZE, Y + (ROW - 1) * SIZE);

    }

    public static void main(String[] args) {
        // 实例化棋盘类对象,调用初始化函数
        GoBangMain go = new GoBangMain();
        go.initUI();
    }

}

 


第二个类:

package gobang228.copy;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

public class GoBangListener implements MouseListener, GoBangDate {
    private Graphics g;
    private int x, y, row, col;
    // 标志位,确认棋子颜色
    private int flag = 1;

    // 构造方法
    public GoBangListener(Graphics g) {
        this.g = g;
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        x = e.getX();
        y = e.getY();
        // 计算点击位置的行和列,确认棋子把棋子放在相应交叉点
        row = Math.round(y / SIZE);
        System.out.println("这个棋子在第" + row + "行!");
        y = Y - CHESSSIZE / 2 + (row - 1) * SIZE;

        col = Math.round(x / SIZE);
        System.out.println("这个棋子在第" + col + "列!");
        x = X - CHESSSIZE / 2 + (col - 1) * SIZE;

        // 确保点击位置在棋盘上
        if (row <= ROW && col <= COLUMN) {
            if (FLAG[row - 1][col - 1] == 0 && flag == 1) {
                g.setColor(Color.black);
                g.fillOval(x, y, CHESSSIZE, CHESSSIZE);
                // 黑棋置1
                FLAG[row - 1][col - 1] = 1;
                flag = 2;
            } else if (FLAG[row - 1][col - 1] == 0 && flag == 2) {
                g.setColor(Color.white);
                g.fillOval(x, y, CHESSSIZE, CHESSSIZE);
                // 白棋置2
                FLAG[row - 1][col - 1] = 2;
                flag = 1;
            }
        }

        // 判断输赢

    }

    @Override
    public void mousePressed(MouseEvent e) {

    }

    @Override
    public void mouseReleased(MouseEvent e) {

    }

    @Override
    public void mouseEntered(MouseEvent e) {

    }

    @Override
    public void mouseExited(MouseEvent e) {

    }

}

 

第三个接口:

package gobang228.copy;

public interface GoBangDate {
    // 设置棋盘面板的起始坐标
    public int X = 50;
    public int Y = 50;
    // 设置棋盘面板的横线竖线个数
    public int ROW = 15;
    public int COLUMN = 15;
    // 设置棋盘面板的格子大小,SIZE为正方形方格的长宽,CHESSSIZE为棋子的长宽
    public int SIZE = 35;
    public int CHESSSIZE = 25;
    // 设置一个二维数组,默认值为0
    public int FLAG[][] = new int[ROW][COLUMN];
}

 

运行结果:我们下了两个棋子,最小化后打开,棋子还在哎!!!

java小程序:五子棋对战的实现_第2张图片


第三部分:解决判断输赢的问题

第一个类:

package gobang31.copy.copy;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;

import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;

//定义棋盘类让其继承面板类,原因为之后要重写棋盘面板类的paint方法,将棋盘面板重置
public class GoBangMain extends JPanel implements GoBangDate {
    // 定义初始化界面函数
    public void initUI() {
        JFrame jf = new JFrame();
        jf.setTitle("五子棋对战");
        jf.setSize(760, 630);
        jf.setDefaultCloseOperation(3);
        jf.setLocationRelativeTo(null);
        jf.setResizable(false);
        // 整体布局为边框布局,JFrame默认布局为边框布局
        jf.setLayout(new BorderLayout());

        // 添加棋盘面板,添加到边框布局的中部
        jf.add(this, BorderLayout.CENTER);
        this.setBackground(Color.gray);

        // 功能面板,默认为流式布局
        JPanel panel = new JPanel();
        panel.setPreferredSize(new Dimension(150, 0));

        JLabel label = new JLabel();
        label.setPreferredSize(new Dimension(140, 120));
        panel.add(label);
        // 添加功能面板
        jf.add(panel, BorderLayout.EAST);
        // 添加功能按钮
        JButton bu1 = new JButton("开始新游戏");
        JButton bu2 = new JButton("悔棋");
        JButton bu3 = new JButton("认输");
        bu1.setPreferredSize(new Dimension(140, 60));
        bu2.setPreferredSize(new Dimension(140, 60));
        bu3.setPreferredSize(new Dimension(140, 60));
        panel.add(bu1);
        panel.add(bu2);
        panel.add(bu3);

        JRadioButton jr1 = new JRadioButton("人人对战");
        JRadioButton jr2 = new JRadioButton("人机对战");
        jr1.setPreferredSize(new Dimension(80, 40));
        jr2.setPreferredSize(new Dimension(80, 40));
        ButtonGroup bg = new ButtonGroup();
        bg.add(jr1);
        bg.add(jr2);
        // 默认选中为jr1按钮,即人人对战
        jr1.setSelected(true);
        panel.add(jr1);
        panel.add(jr2);
        // 复选框
        JCheckBox jc = new JCheckBox("AI先手");
        jc.setPreferredSize(new Dimension(80, 40));
        panel.add(jc);

        jf.setVisible(true);
        // 实例化画笔对象
        Graphics g = this.getGraphics();
        // 实例化监听接口,并传参,参数为画笔对象
        GoBangListener gl = new GoBangListener(g, this);
        this.addMouseListener(gl);
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        // 调用棋盘面板初始化的方法,使棋盘面板初始化
        drawChessBorder(g);
        // 棋盘面板的重绘
        for (int r = 0; r < FLAG.length; r++) {
            for (int c = 0; c < FLAG[r].length; c++) {
                if (FLAG[r][c] != 0) {
                    int x = X + c * SIZE - CHESSSIZE / 2;
                    int y = Y + r * SIZE - CHESSSIZE / 2;
                    if (FLAG[r][c] == 1) {
                        g.setColor(Color.BLACK);
                    } else {
                        g.setColor(Color.white);
                    }
                    g.fillOval(x, y, CHESSSIZE, CHESSSIZE);

                }

            }
        }

    }

    // 定义棋盘面板初始化的方法
    private void drawChessBorder(Graphics g) {
        for (int i = 0; i < ROW; i++)
            g.drawLine(X, Y + i * SIZE, X + (COLUMN - 1) * SIZE, Y + i * SIZE);
        for (int i = 0; i < COLUMN; i++)
            g.drawLine(X + i * SIZE, Y, X + i * SIZE, Y + (ROW - 1) * SIZE);

    }

    public static void main(String[] args) {
        // 实例化棋盘类对象,调用初始化函数
        GoBangMain go = new GoBangMain();
        go.initUI();
    }

}

 

第二个类:

package gobang31.copy.copy;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.JOptionPane;

public class GoBangListener implements MouseListener, GoBangDate {

    private Graphics g;
    private int x, y, row, col;
    // 标志位,确认棋子颜色
    private int flag = 1;
    private String str;
    private GoBangMain gobangMain;

    // 构造方法
    public GoBangListener(Graphics g, GoBangMain gobangMain) {
        this.g = g;
        this.gobangMain = gobangMain;
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        x = e.getX();
        y = e.getY();
        // 计算点击位置的行和列,确认棋子把棋子放在相应交叉点
        // row为棋子行数,col为棋子列数,row范围为1-15,col也是
        // x,y为棋子左上角的坐标值
        row = Math.round(y / SIZE);
        y = Y - CHESSSIZE / 2 + (row - 1) * SIZE;
        col = Math.round(x / SIZE);
        x = X - CHESSSIZE / 2 + (col - 1) * SIZE;

        // 确保点击位置在棋盘上
        if (row <= ROW && col <= COLUMN) {
            if (FLAG[row - 1][col - 1] == 0 && flag == 1) {
                g.setColor(Color.black);
                g.fillOval(x, y, CHESSSIZE, CHESSSIZE);
                // 黑棋置1
                // FLAG为二维数组,起始位置为FLAG[0][0],此时row和col值均为1,故两者需要减去1
                FLAG[row - 1][col - 1] = 1;
                flag = 2;
            } else if (FLAG[row - 1][col - 1] == 0 && flag == 2) {
                g.setColor(Color.white);
                g.fillOval(x, y, CHESSSIZE, CHESSSIZE);
                // 白棋置2
                FLAG[row - 1][col - 1] = 2;
                flag = 1;
            }
        }

        // 判断输赢
        if (GoBangWin.validate(row, col)) {
            if (FLAG[row - 1][col - 1] == 1) {
                str = "黑棋胜利!";
            } else if (FLAG[row - 1][col - 1] == 2) {
                str = "白棋胜利!";
            }
            JOptionPane.showMessageDialog(gobangMain, str);

        }
    }

    @Override
    public void mousePressed(MouseEvent e) {

    }

    @Override
    public void mouseReleased(MouseEvent e) {

    }

    @Override
    public void mouseEntered(MouseEvent e) {

    }

    @Override
    public void mouseExited(MouseEvent e) {

    }

}

 


第三个接口:

package gobang31.copy.copy;

public interface GoBangDate {
    // 设置棋盘面板的起始坐标
    public int X = 50;
    public int Y = 50;
    // 设置棋盘面板的横线竖线个数
    public int ROW = 15;
    public int COLUMN = 15;
    // 设置棋盘面板的格子大小,SIZE为正方形方格的长宽,CHESSSIZE为棋子的长宽
    public int SIZE = 35;
    public int CHESSSIZE = 25;
    // 设置一个二维数组,默认值为0
    public int FLAG[][] = new int[ROW][COLUMN];
}

 


第四个类:在这里定义了判断胜利的方法,方法为以鼠标点击位置为原点,分别判断左,右,上,下,左上,左下,右上,右下八个方向的跟所下棋子颜色相同的棋子个数是否大于等于5

package gobang31.copy.copy;

public class GoBangWin implements GoBangDate {
    // 判断同一行上颜色相同的棋子个数是否大于等于5
    // 参数为r(该棋子所在的行),c(该棋子所在的列)
    public static boolean validate(int r, int c) {
        if (countZ(r, c) >= 5 || countY(r, c) >= 5 || countX(r, c) >= 5 || countS(r, c) >= 5 || countZS(r, c) >= 5
                || countZX(r, c) >= 5 || countYS(r, c) >= 5 || countYX(r, c) >= 5) {
            return true;
        } else {
            return false;
        }
    }

    // 计算同一行上颜色相同的棋子个数
    // 参数为row(该棋子所在的行),col(该棋子所在的列)
    public static int countZ(int row, int col) {
        int count = 1;
        for (int col1 = col - 1; col1 > 0; col1--) {
            if (FLAG[row - 1][col1 - 1] == FLAG[row - 1][col - 1]) {
                count++;
            } else {
                break;
            }
        }
        return count;
    }

    public static int countY(int row, int col) {
        int count = 1;
        for (int col1 = col + 1; col1 < COLUMN; col1++) {
            if (FLAG[row - 1][col1 - 1] == FLAG[row - 1][col - 1]) {
                count++;
            } else {
                break;
            }
        }
        return count;
    }

    public static int countX(int row, int col) {
        int count = 1;
        for (int row1 = row + 1; row1 < ROW; row1++) {
            if (FLAG[row1 - 1][col - 1] == FLAG[row - 1][col - 1]) {
                count++;
            } else {
                break;
            }
        }
        return count;
    }

    public static int countS(int row, int col) {
        int count = 1;
        for (int row1 = row - 1; row1 > 0; row1--) {
            if (FLAG[row1 - 1][col - 1] == FLAG[row - 1][col - 1]) {
                count++;
            } else {
                break;
            }
        }
        return count;
    }

    public static int countZS(int row, int col) {
        int count = 1;
        for (int row1 = row - 1, col1 = col - 1; row1 > 0 && col1 > 0; row1--, col1--) {
            if (FLAG[row1 - 1][col1 - 1] == FLAG[row - 1][col - 1]) {
                count++;
            } else {
                break;
            }

        }
        return count;
    }

    public static int countYX(int row, int col) {
        int count = 1;
        for (int row1 = row + 1, col1 = col + 1; row1 < ROW && col1 < COLUMN; row1++, col1++) {
            if (FLAG[row1 - 1][col1 - 1] == FLAG[row - 1][col - 1]) {
                count++;
            } else {
                break;
            }

        }
        return count;
    }

    public static int countZX(int row, int col) {
        int count = 1;
        for (int row1 = row + 1, col1 = col - 1; row1 < ROW && col1 > 0; row1++, col1--) {
            if (FLAG[row1 - 1][col1 - 1] == FLAG[row - 1][col - 1]) {
                count++;
            } else {
                break;
            }

        }
        return count;
    }

    public static int countYS(int row, int col) {
        int count = 1;
        for (int row1 = row - 1, col1 = col + 1; row1 > 0 && col1 < COLUMN; row1--, col1++) {
            if (FLAG[row1 - 1][col1 - 1] == FLAG[row - 1][col - 1]) {
                count++;
            } else {
                break;
            }

        }
        return count;
    }

}

 

运行结果:我们知道如何判断输赢了哎!

java小程序:五子棋对战的实现_第3张图片

第四部分:实现功能按钮面板的功能,让棋盘游戏更加贴近真实状况

第一个类:

package gobang32.copy.copy.copy;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;

import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;

//定义棋盘类让其继承面板类,原因为之后要重写棋盘面板类的paint方法,将棋盘面板重置
public class GoBangMain extends JPanel implements GoBangDate {
    // 定义初始化界面函数
    public void initUI() {
        JFrame jf = new JFrame();
        jf.setTitle("五子棋对战");
        jf.setSize(760, 630);
        jf.setDefaultCloseOperation(3);
        jf.setLocationRelativeTo(null);
        jf.setResizable(false);
        // 整体布局为边框布局,JFrame默认布局为边框布局
        jf.setLayout(new BorderLayout());

        // 添加棋盘面板,添加到边框布局的中部
        jf.add(this, BorderLayout.CENTER);
        this.setBackground(Color.gray);

        // 功能面板,默认为流式布局
        JPanel panel = new JPanel();
        panel.setPreferredSize(new Dimension(150, 0));
        // 在功能面板上方添加空白区域
        JLabel label = new JLabel();
        label.setPreferredSize(new Dimension(140, 120));
        panel.add(label);
        // 添加功能面板
        jf.add(panel, BorderLayout.EAST);
        // 添加功能按钮
        JButton bu1 = new JButton("开始新游戏");
        JButton bu2 = new JButton("悔棋");
        JButton bu3 = new JButton("认输");
        bu1.setPreferredSize(new Dimension(140, 60));
        bu2.setPreferredSize(new Dimension(140, 60));
        bu3.setPreferredSize(new Dimension(140, 60));
        panel.add(bu1);
        panel.add(bu2);
        panel.add(bu3);

        JRadioButton jr1 = new JRadioButton("人人对战");
        JRadioButton jr2 = new JRadioButton("人机对战");
        jr1.setPreferredSize(new Dimension(80, 40));
        jr2.setPreferredSize(new Dimension(80, 40));
        ButtonGroup bg = new ButtonGroup();
        bg.add(jr1);
        bg.add(jr2);
        // 默认选中为jr1按钮,即人人对战
        jr1.setSelected(true);
        panel.add(jr1);
        panel.add(jr2);
        // 复选框
        JCheckBox jc = new JCheckBox("AI先手");
        jc.setPreferredSize(new Dimension(80, 40));
        panel.add(jc);
        jc.setEnabled(false);

        jf.setVisible(true);
        // 实例化监听接口
        GoBangListener gl = new GoBangListener(this, bu1, bu2, bu3, jr1, jr2, jc);

        bu1.addActionListener(gl);
        bu2.addActionListener(gl);
        bu2.setEnabled(false);
        bu3.addActionListener(gl);
        bu3.setEnabled(false);
        jr1.addActionListener(gl);
        jr2.addActionListener(gl);
        jc.addActionListener(gl);

    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        // 调用棋盘面板初始化的方法,使棋盘面板初始化
        drawChessBorder(g);
        // 棋盘面板的重绘
        for (int r = 0; r < FLAG.length; r++) {
            for (int c = 0; c < FLAG[r].length; c++) {
                if (FLAG[r][c] != 0) {
                    int x = X + c * SIZE - CHESSSIZE / 2;
                    int y = Y + r * SIZE - CHESSSIZE / 2;
                    if (FLAG[r][c] == 1) {
                        g.setColor(Color.BLACK);
                    } else {
                        g.setColor(Color.white);
                    }
                    g.fillOval(x, y, CHESSSIZE, CHESSSIZE);

                }

            }
        }

    }

    // 定义棋盘面板初始化的方法
    private void drawChessBorder(Graphics g) {
        for (int i = 0; i < ROW; i++)
            g.drawLine(X, Y + i * SIZE, X + (COLUMN - 1) * SIZE, Y + i * SIZE);
        for (int i = 0; i < COLUMN; i++)
            g.drawLine(X + i * SIZE, Y, X + i * SIZE, Y + (ROW - 1) * SIZE);

    }

    public static void main(String[] args) {
        // 实例化棋盘类对象,调用初始化函数
        GoBangMain go = new GoBangMain();
        go.initUI();
    }

}

 


第二个类:

package gobang32.copy.copy.copy;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JOptionPane;
import javax.swing.JRadioButton;

public class GoBangListener implements MouseListener, GoBangDate, ActionListener {

    private Graphics g;
    private int x, y, row, col;
    // 标志位,确认棋子颜色
    private int flag = 1;
    private String str, str1;
    private GoBangMain gobangMain;
    private JButton bu1, bu2, bu3;
    private JRadioButton jr1, jr2;
    private JCheckBox jc;
    private String ss = "人人对战";
    private ArrayList list = new ArrayList();

    // 构造方法
    public GoBangListener(GoBangMain gobangMain, JButton bu1, JButton bu2, JButton bu3, JRadioButton jr1,
            JRadioButton jr2, JCheckBox jc) {
        this.gobangMain = gobangMain;
        this.bu1 = bu1;
        this.bu2 = bu2;
        this.bu3 = bu3;
        this.jr1 = jr1;
        this.jr2 = jr2;
        this.jc = jc;

    }

    @Override
    public void mouseClicked(MouseEvent e) {
        x = e.getX();
        y = e.getY();
        // 计算点击位置的行和列,确认棋子把棋子放在相应交叉点
        // row为棋子行数,col为棋子列数,row范围为1-15,col也是
        // x,y为棋子左上角的坐标值
        if (ss.equals("人人对战")) {
            row = Math.round(y / SIZE);
            y = Y - CHESSSIZE / 2 + (row - 1) * SIZE;
            col = Math.round(x / SIZE);
            x = X - CHESSSIZE / 2 + (col - 1) * SIZE;

            list.add(new Point(row, col));
            System.out.println("这个数组队列大小为:" + list.size());

            // 确保点击位置在棋盘上
            if (row <= ROW && col <= COLUMN) {
                if (FLAG[row - 1][col - 1] == 0 && flag == 1) {
                    g.setColor(Color.black);
                    g.fillOval(x, y, CHESSSIZE, CHESSSIZE);
                    // 黑棋置1
                    // FLAG为二维数组,起始位置为FLAG[0][0],此时row和col值均为1,故两者需要减去1
                    FLAG[row - 1][col - 1] = 1;
                    // 下一个棋子时白棋
                    flag = 2;
                } else if (FLAG[row - 1][col - 1] == 0 && flag == 2) {
                    g.setColor(Color.white);
                    g.fillOval(x, y, CHESSSIZE, CHESSSIZE);
                    // 白棋置2
                    FLAG[row - 1][col - 1] = 2;
                    // 下一个棋子是黑棋
                    flag = 1;
                }
            }

            // 判断输赢
            if (GoBangWin.validate(row, col)) {
                if (FLAG[row - 1][col - 1] == 1) {
                    str = "黑棋胜利!";
                } else if (FLAG[row - 1][col - 1] == 2) {
                    str = "白棋胜利!";
                }
                JOptionPane.showMessageDialog(gobangMain, str);
                // 胜利之后也不能继续落子了
                gobangMain.removeMouseListener(this);
                bu1.setEnabled(true);
                bu2.setEnabled(false);
                bu3.setEnabled(false);
                jr1.setEnabled(true);
                jr2.setEnabled(true);

            }
        } else {
            JOptionPane.showMessageDialog(gobangMain, "人机对战还未实现,请稍后。。。");

        }
    }

    @Override
    public void mousePressed(MouseEvent e) {

    }

    @Override
    public void mouseReleased(MouseEvent e) {

    }

    @Override
    public void mouseEntered(MouseEvent e) {

    }

    @Override
    public void mouseExited(MouseEvent e) {

    }

    @Override
    public void actionPerformed(ActionEvent e) {
        // 获取按钮文字信息
        String s = e.getActionCommand();
        if (s.equals("开始新游戏")) {
            g = gobangMain.getGraphics();

            bu1.setEnabled(false);
            bu2.setEnabled(true);
            bu3.setEnabled(true);
            jr1.setEnabled(false);
            jr2.setEnabled(false);
            jc.setEnabled(false);

            // 清除二维数组中的内容
            for (int r = 0; r < FLAG.length; r++) {
                for (int c = 0; c < FLAG[r].length; c++) {
                    FLAG[r][c] = 0;
                }
            }
            // 棋盘界面重绘
            gobangMain.paint(g);
            // 标志位置1位黑棋优先
            flag = 1;
            // 开始新游戏之后棋盘界面才能被监听,也就是开始下棋
            gobangMain.addMouseListener(this);

        } else if (s.equals("悔棋")) {
            if (ss.equals("人人对战")) {
                if (list.size() > 2) {
                    Point p = list.remove(list.size() - 1);
                    System.out.println("此时这个数组队列大小为:" + list.size());

                    FLAG[p.x - 1][p.y - 1] = 0;
                    gobangMain.paint(g);
                    if (flag == 1) {
                        flag = 2;
                    } else if (flag == 2) {
                        flag = 1;
                    }
                }

            } else if (ss.equals("人机对战")) {
                // 人机对战悔棋代码
            }
        } else if (s.equals("认输")) {
            if (ss.equals("人人对战")) {
                // flag等于1说明轮到黑棋方下棋
                if (flag == 1) {
                    str1 = "黑棋认输,白棋胜利!";
                } else if (flag == 2) {
                    str1 = "白棋认输,黑棋胜利!";
                }
                JOptionPane.showMessageDialog(gobangMain, str1);
                // 认输之后不能继续落子了
                gobangMain.removeMouseListener(this);
                bu1.setEnabled(true);
                bu2.setEnabled(false);
                bu3.setEnabled(false);
                jr1.setEnabled(true);
                jr2.setEnabled(true);
            } else {
                // 此处应该为人机对战认输代码
            }

        } else if (s.equals("人人对战")) {
            jc.setEnabled(false);
            ss = s;
        } else if (s.equals("人机对战")) {
            jc.setEnabled(true);
            ss = s;
        } else if (s.equals("AI先手")) {

        }

    }

}

 


第三个接口:

package gobang32.copy.copy.copy;

public interface GoBangDate {
    // 设置棋盘面板的起始坐标
    public int X = 50;
    public int Y = 50;
    // 设置棋盘面板的横线竖线个数
    public int ROW = 15;
    public int COLUMN = 15;
    // 设置棋盘面板的格子大小,SIZE为正方形方格的长宽,CHESSSIZE为棋子的长宽
    public int SIZE = 35;
    public int CHESSSIZE = 25;
    // 设置一个二维数组,默认值为0
    public int FLAG[][] = new int[ROW][COLUMN];
}

 


第四个类:

package gobang32.copy.copy.copy;

public class GoBangWin implements GoBangDate {
    // 判断同一行上颜色相同的棋子个数是否大于等于5
    // 参数为r(该棋子所在的行),c(该棋子所在的列)
    public static boolean validate(int r, int c) {
        if (countZ(r, c) >= 5 || countY(r, c) >= 5 || countX(r, c) >= 5 || countS(r, c) >= 5 || countZS(r, c) >= 5
                || countZX(r, c) >= 5 || countYS(r, c) >= 5 || countYX(r, c) >= 5) {
            return true;
        } else {
            return false;
        }
    }

    // 计算同一行上颜色相同的棋子个数
    // 参数为row(该棋子所在的行),col(该棋子所在的列)
    public static int countZ(int row, int col) {
        int count = 1;
        for (int col1 = col - 1; col1 > 0; col1--) {
            if (FLAG[row - 1][col1 - 1] == FLAG[row - 1][col - 1]) {
                count++;
            } else {
                break;
            }
        }
        return count;
    }

    public static int countY(int row, int col) {
        int count = 1;
        for (int col1 = col + 1; col1 < COLUMN; col1++) {
            if (FLAG[row - 1][col1 - 1] == FLAG[row - 1][col - 1]) {
                count++;
            } else {
                break;
            }
        }
        return count;
    }

    public static int countX(int row, int col) {
        int count = 1;
        for (int row1 = row + 1; row1 < ROW; row1++) {
            if (FLAG[row1 - 1][col - 1] == FLAG[row - 1][col - 1]) {
                count++;
            } else {
                break;
            }
        }
        return count;
    }

    public static int countS(int row, int col) {
        int count = 1;
        for (int row1 = row - 1; row1 > 0; row1--) {
            if (FLAG[row1 - 1][col - 1] == FLAG[row - 1][col - 1]) {
                count++;
            } else {
                break;
            }
        }
        return count;
    }

    public static int countZS(int row, int col) {
        int count = 1;
        for (int row1 = row - 1, col1 = col - 1; row1 > 0 && col1 > 0; row1--, col1--) {
            if (FLAG[row1 - 1][col1 - 1] == FLAG[row - 1][col - 1]) {
                count++;
            } else {
                break;
            }

        }
        return count;
    }

    public static int countYX(int row, int col) {
        int count = 1;
        for (int row1 = row + 1, col1 = col + 1; row1 < ROW && col1 < COLUMN; row1++, col1++) {
            if (FLAG[row1 - 1][col1 - 1] == FLAG[row - 1][col - 1]) {
                count++;
            } else {
                break;
            }

        }
        return count;
    }

    public static int countZX(int row, int col) {
        int count = 1;
        for (int row1 = row + 1, col1 = col - 1; row1 < ROW && col1 > 0; row1++, col1--) {
            if (FLAG[row1 - 1][col1 - 1] == FLAG[row - 1][col - 1]) {
                count++;
            } else {
                break;
            }

        }
        return count;
    }

    public static int countYS(int row, int col) {
        int count = 1;
        for (int row1 = row - 1, col1 = col + 1; row1 > 0 && col1 < COLUMN; row1--, col1++) {
            if (FLAG[row1 - 1][col1 - 1] == FLAG[row - 1][col - 1]) {
                count++;
            } else {
                break;
            }

        }
        return count;
    }

}

 


运行结果:这是初始化界面,只有“开始新游戏”,“人人”,“人机对战可以被选择”,默认选中“人人”,当选中人机时,复选框“AI先手”可以被选中,而且未点击“开始新游戏”不能落下棋子,即没有开启棋盘面板的监听

java小程序:五子棋对战的实现_第4张图片

当点击“开始新游戏”按钮后,只有“悔棋”,“认输”按钮可以选中

java小程序:五子棋对战的实现_第5张图片

下面我们开始下棋

java小程序:五子棋对战的实现_第6张图片

胜利之后不能继续在棋盘面板上下棋(撤去监听),把按钮是否可选置为初始化状态

java小程序:五子棋对战的实现_第7张图片

认输:认输后也不能继续下棋了(撤去监听),功能按钮置位初始化状态

如何确定哪方认输?

是通过棋子标志位来参控的。

java小程序:五子棋对战的实现_第8张图片

悔棋:

悔棋前状态:

java小程序:五子棋对战的实现_第9张图片

悔棋后状态:

java小程序:五子棋对战的实现_第10张图片

但是不能无限悔棋,棋子最少有两颗。

人机对战:

java小程序:五子棋对战的实现_第11张图片

 

未完待续。。。

 

 

 

 

 

 

 

你可能感兴趣的:(蓝杰培训)