Java五子棋

今天来分享一个Java五子棋。

所涉及到的知识
1. 画图板的重绘
2. 权值算法

接口

首先定义一个BorderSize的接口,用来设置棋盘和棋子的相关属性。凡是需要用到接口中相关属性的类都必须实现BorderSize接口。

public interface BorderSize {
    int SIZE = 50;
    int ROW = 19;
    int COLUM = 19;
    int X = 30;
    int Y = 30;
    int[][] chessArray = new int[ROW][COLUM];
    int[][] weightArray = new int[ROW][COLUM];

}

棋盘界面类

棋盘界面类中主要定义了界面的样式以及重绘方法

public class ChessBorder extends JPanel implements BorderSize{

    public void showBorder(){
        JFrame frame = new JFrame();
        frame.setTitle("我的五子棋");
        frame.setSize(1100, 1000);
        //设置窗体不可改变大小
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //设置棋盘背景图片
        ImageIcon centerIcon = new ImageIcon("C:\\Users\\sunxiaona\\Desktop\\Java\\蓝杰\\Image\\4.jpg");
        JLabel centerLabel = new JLabel(centerIcon);
        this.add(centerLabel);
        //设置容器为边框布局
        frame.setLayout(new BorderLayout());
        //this.setBackground(Color.LIGHT_GRAY);
        frame.add(this, BorderLayout.CENTER);
        //添加按钮面板并设置大小
        JPanel eastPanel = new JPanel();
        eastPanel.setBackground(Color.DARK_GRAY);
        Dimension eastPsize = new Dimension(120,1000);
        eastPanel.setPreferredSize(eastPsize);
        frame.add(eastPanel, BorderLayout.EAST);
        //添加标签,使按钮居中
        JLabel label = new JLabel();
        Dimension labelSize = new Dimension(110,300);
        label.setPreferredSize(labelSize);
        eastPanel.add(label);
        //创建监听器对象
        BorderListener BL = new BorderListener();
        //添加鼠标监听器到棋盘面板
        //this.addMouseListener(BL);
        //设置按钮的大小
        Dimension buttonSize = new Dimension(110,50);
        String[] btn ={"开始新游戏","认输","悔棋"};
        for(int i=0;i<btn.length;i++){
            JButton button = new JButton(btn[i]);
            button.setPreferredSize(buttonSize);
            button.addActionListener(BL);
            eastPanel.add(button);
        }
        String[] item = {"人人对战","人机对战"};
        JComboBox<String> JCB = new JComboBox<String>(item);
        JCB.setPreferredSize(buttonSize);
        eastPanel.add(JCB);
        JCB.addActionListener(BL);

        //显示可见
        frame.setVisible(true);
        BL.setPanel(this);
        BL.setJCB(JCB);
        BL.setCHB(this);
    }

    public void paint(Graphics g){
        super.paint(g);
        for(int i=0;i<ROW;i++){
            //画横线
            g.drawLine(X,Y+SIZE*i,X+(ROW-1)*SIZE,Y+SIZE*i);
            g.drawLine(X+SIZE*i, Y, X+SIZE*i,Y+SIZE*(COLUM-1));
        }
        //画棋子
        for(int i=0;i<ROW;i++){
            for(int j=0;j<COLUM;j++){
                if(chessArray[i][j]==1){
                    g.setColor(Color.BLACK);
                    g.fillOval(X+i*SIZE-SIZE/2, Y+j*SIZE-SIZE/2, SIZE, SIZE);
                }
                if(chessArray[i][j]==2){
                    g.setColor(Color.WHITE);
                    g.fillOval(X+i*SIZE-SIZE/2, Y+j*SIZE-SIZE/2, SIZE, SIZE);
                }
            }
        }
    }

    public static void main(String[] args){
        ChessBorder CHB = new ChessBorder();
        CHB.showBorder();
    }

监听器类

所有的逻辑实现全部在监听器类中,在本五子棋中有“人人对战”和“人机对战”两种对战模式,并且有开始新游戏、悔棋、认输等操作。所有的这些操作所产生的效果都在监听器类中定义了。细节之处见代码!


import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.JComboBox;
import javax.swing.JOptionPane;
import javax.swing.JPanel;


public class BorderListener implements BorderSize,MouseListener,ActionListener{
    int x,y;
    JPanel panel;
    JComboBox JCB;
    ChessBorder CHB;
    int count = 0;
    String fightType = "人人对战";
    int huiX,huiY;
    int max,row,colum;  //人机大战需要用的数据

    //获取画布
    public void setPanel(JPanel panel){
        this.panel = panel;
    }
    //传递JComboBox
    public void setJCB(JComboBox JCB){
        this.JCB = JCB;
    }
    //传递ChessBorder
    public void setCHB(ChessBorder CHB){
        this.CHB = CHB;
    }
    public void actionPerformed(ActionEvent e){
        String action = e.getActionCommand();
        if("开始新游戏".equals(action)){
            //清空棋盘
            for(int i=0;i<ROW;i++){
                for(int j=0;j<COLUM;j++){
                    chessArray[i][j] = 0;
                }
            }
            //设置JComboBox不可用
            JCB.setEnabled(false);
            panel.addMouseListener(this);
            //画的时候获取画布(游戏重新开始后清空画板)
            Graphics g = panel.getGraphics();
            Graphics2D g2d = (Graphics2D) g;
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
            CHB.paint(g);
        }else if("认输".equals(action)){
            if(count==0){
                JOptionPane.showMessageDialog(null, "白棋获胜!!!");
            }else {
                JOptionPane.showMessageDialog(null, "黑棋获胜!!!");
            }
            //黑棋先下
            count = 0;
            JCB.setEnabled(true);
            panel.removeMouseListener(this);
        }else if("悔棋".equals(action)){
            chessArray[huiX][huiY] = 0;
            Graphics g = panel.getGraphics();
            //抗锯齿效果
            Graphics2D g2d = (Graphics2D) g;
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
            if(count==0){
                count = 1;
            }else {
                count = 0;
            }
            CHB.paint(g);
        }else {
            String s =(String)JCB.getSelectedItem();
            fightType = s;
        }
    }

    public void mouseReleased(MouseEvent e){
        x = e.getX();
        y = e.getY();
        Result result = new Result();
        if(panel!=null){
            Graphics g = panel.getGraphics();
            //抗锯齿处理 添加此行后,棋子边缘光滑 
            Graphics2D g2d = (Graphics2D) g;
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
            int index = 0;
            int r,c;
            for(int i=X;i<=(ROW-1)*SIZE;i=i+SIZE){
                for(int j=Y;j<=(COLUM-1)*SIZE;j=j+SIZE){
                    if((x-i>-SIZE/2&&x-i<SIZE/2)&&(y-j>-SIZE/2&&y-j<SIZE/2)){
                        r = (i-X)/SIZE;
                        c = (j-Y)/SIZE;
                        //画黑棋
                        if(count==0 && chessArray[r][c]!=1 && chessArray[r][c]!=2){
                            chessArray[r][c] = 1;
                            g.setColor(Color.BLACK);
                            g.fillOval(i-SIZE/2, j-SIZE/2, SIZE, SIZE);
                            count++;    //转换到白棋
                            result.r = r;
                            result.c = c;
                            //悔棋的棋子
                            huiX = r;
                            huiY = c;
                        }
                        //画白棋
                        if(count==1 && chessArray[r][c]!=1 && chessArray[r][c]!=2){
                            chessArray[r][c] = 2;
                            g.setColor(Color.WHITE);
                            g.fillOval(i-SIZE/2, j-SIZE/2, SIZE, SIZE);
                            count--;    //转换到黑棋
                            result.r = r;
                            result.c = c;
                            //悔棋的棋子
                            huiX = r;
                            huiY = c;
                        }

                    }
                }
            }
            //(人人对战判断黑白棋胜利)和(人机对战判断黑棋部分)
            if(result.WinOrLoss()){
                if(chessArray[result.r][result.c]==1){
                    JOptionPane.showMessageDialog(null, "黑棋获胜!");
                }
                if(chessArray[result.r][result.c]==2){
                    JOptionPane.showMessageDialog(null, "白棋胜利!");
                }
                //重新开始后黑棋先下
                count = 0;  
                //游戏结束后设置下拉列表框为可用
                JCB.setEnabled(true);
                //游戏结束后不可继续下棋  (移除鼠标监听器)
                panel.removeMouseListener(this);
            }
            //人机对战部分
            if("人机对战".equals(fightType)){
                AI ai = new AI();
                ai.AIplay();
                int max=0;
                //寻找最大权重
                for(int i=0;i<ROW;i++){
                    for(int j=0;j<COLUM;j++){
                        if(weightArray[i][j]>max){
                            max = weightArray[i][j];
                            row = i;
                            colum = j;
                        }
                        System.out.print(weightArray[i][j]+" ");
                    }
                    System.out.println();
                }
                System.out.println(max);
                //人机对战中画电脑的棋子
                if(count==1){
                    chessArray[row][colum] = 2;
                    g.setColor(Color.WHITE);
                    System.out.println(row+" "+colum);
                    g.fillOval(row*SIZE+X-SIZE/2,colum*SIZE+Y-SIZE/2 ,SIZE, SIZE);
                    count--;
                }
            result.r = row;
            result.c = colum;
            }
            if(result.WinOrLoss()&&"人机对战".equals(fightType)){
                if(chessArray[row][colum]==2){
                    JOptionPane.showMessageDialog(null, "白棋胜利!");
                    row = 0;
                    colum = 0;
                }
                //重新开始后黑棋先下
                count = 0;  
                //游戏结束后设置下拉列表框为可用
                JCB.setEnabled(true);
                //游戏结束后不可继续下棋  (移除鼠标监听器)
                panel.removeMouseListener(this);

            }
        }
    }


    public void mouseClicked(MouseEvent e){}
    public void mousePressed(MouseEvent e){}
    public void mouseEntered(MouseEvent e){}
    public void mouseExited(MouseEvent e){}

}

Win Or Lost

实现了上述内容之后,我们已经可以在棋盘上顺利下棋了,那么接下来当然是判断输赢了。判断输赢分别从4个方向上统计:水平、垂直、左斜、右斜。只要搞清楚原理即可,这部分的代码大同小异,基本上都是重复工作。

package goBang;

public class Result implements BorderSize{

    boolean flag = false;
    int r,c;

    public boolean WinOrLoss(){

        if(resultH(r,c)>=5||resultS(r,c)>=5||resultL(r,c)>=5||resultR(r,c)>=5){
            return !flag;
        }else {
            return flag;
        }

    }

    //横向判断
        public int resultH(int r,int c){
            int count=1;
            //往左走
            for(int i=c-1;i>=0;i--){
                if(chessArray[r][c]==chessArray[r][i]&&chessArray[r][i]!=0){
                    count++;
                }else {
                    break;
                }
            }
            //往右走
            for(int i=c+1;i<ROW;i++){
                if(chessArray[r][c]==chessArray[r][i]&&chessArray[r][i]!=0){
                    count++;
                }else {
                    break;
                }
            }
            return count;
        }

        //竖向判断
        public int resultS(int r,int c){
            int count=1;
            //往上走
            for(int i=r-1;i>=0;i--){
                if(chessArray[r][c]==chessArray[i][c]&&chessArray[i][c]!=0){
                    count++;
                }else {
                    break;
                }
            }
            //往下走
            for(int i=r+1;i<ROW;i++){
                if(chessArray[r][c]==chessArray[i][c]&&chessArray[i][c]!=0){
                    count++;
                }else {
                    break;
                }
            }
            return count;
        }
        //斜向判断(左上到右下)
        public int resultL(int r,int c){
            int count=1;
            //往左走
            for(int i=r-1,j=c-1;i>=0&&j>=0;i--,j--){
                if(chessArray[i][j]==chessArray[r][c]&&chessArray[i][j]!=0){
                    count++;
                }else{
                    break;
                }
            }
            //往右走
            for(int i=r+1,j=c+1;i<ROW&&j<COLUM;i++,j++){
                if(chessArray[i][j]==chessArray[r][c]&&chessArray[i][j]!=0){
                    count++;
                }else {
                    break;
                }
            }
            return count;
        }
        //斜向判断(左下到右上)
        public int resultR(int r,int c){
            int count=1;
            //往左走
            for(int i=r+1,j=c-1;i<ROW&&j>=0;i++,j--){
                if(chessArray[i][j]==chessArray[r][c]&&chessArray[i][j]!=0){
                    count++;
                }else {
                    break;
                }
            }
            //往右走
            for(int i=r-1,j=c+1;i>=0&&j<ROW;i--,j++){
                if(chessArray[i][j]==chessArray[r][c]&&chessArray[i][j]!=0){
                    count++;
                }else {
                    break;
                }
            }
            return count;
        }

}

AI

如果想为我们的五子棋增添一点点人工智能的色彩,就需要知道如何指挥电脑下棋了。想深入了解的小伙伴可以参考一下权值算法、博弈树….我用的是权值算法(下面内容,算法不是特别完善哈,你们可以参考参考自己写一个更厉害的AI)

package goBang;

import java.util.HashMap;

public class AI implements BorderSize{

    static HashMap<String,Integer> map = new HashMap<String,Integer>();
    static {
        //防守
        map.put("0", 1);
        map.put("010",10);
        map.put("021", 15);
        map.put("0112",20);
        map.put("0221",150);
        map.put("02221",400);
        map.put("01112",500);
        map.put("0110", 800);
        map.put("022221", 5000);
        map.put("01110", 2000);
        map.put("011112", 7000);
        map.put("02020", 300);
        map.put("02220", 5000);
        map.put("020", 25);
        map.put("0220",280);
        map.put("022220",100000);
        map.put("01111", 4000);
        map.put("02", 5);


    }

    //判断每个点的权值
        public void AIplay(){
            for(int i=0;i<ROW;i++){
                for(int j=0;j<COLUM;j++){
                    weightArray[i][j]=0;
                }
            }
            for(int r=0;r<ROW;r++){
                for(int c=0;c<COLUM;c++){
                    if(chessArray[r][c]==0){        //判断该位是否为空位
                        //水平方向
                        String code = "0";  //用来记录棋子相连的情况
                        int chess = 0;   //记录第一次出现的棋子
                        int number = 0; //记录空位出现的次数
                        //水平向左统计
                        for(int i=c-1;i>=0;i--){
                            if(chessArray[r][i]==0){//判断是否为空位
                                if(c==i+1){
                                    break;  //如果有两个连续的空位,跳出
                                }else if(number==0){    //第一次出现空位
                                    code = code +chessArray[r][i];  //记录棋子相连的情况
                                    number++;
                                }else if(number==1){    //第二次出现空位
                                    if(chessArray[r][i]==chessArray[r][i+1]){   //判断是否又为2个连续的空位
                                        break;
                                    }
                                    code = code +chessArray[r][i];
                                    number++;
                                }else if(number==2){    //第三次出现空位
                                    if(chessArray[r][i]==chessArray[r][i+1]){   //空位连续
                                        break;
                                    }
                                }
                            }else{      //该位是棋子
                                if(chess==0){   //第一次出现棋子
                                    chess =chessArray[r][i];
                                    code = code +chessArray[r][i];
                                }else if(chess==chessArray[r][i]){
                                    code = code +chessArray[r][i];
                                }else {
                                    code = code +chessArray[r][i];
                                    break;
                                }
                            }
                        }
                        System.out.print(code+" ");
                        Integer value0 = map.get(code); //Inter 整数类
                        if(value0!=null){
                            weightArray[r][c] += value0;
                        }
                        code = "0";
                        chess = 0;
                        number=0;
                        //水平向右统计
                        for(int i=c+1;i<COLUM;i++){
                            if(chessArray[r][i]==0){
                                if(c==i-1){
                                    break;  //相邻2空位,跳出
                                }else if(number==0){    //第一次出现空位
                                    code = code +chessArray[r][i];
                                    number++;
                                }else if(number==1){    ////第2次出现空位
                                    if(chessArray[r][i]==chessArray[r][i-1]){
                                        break;      //连续2空位跳出
                                    }else{
                                        code = code + chessArray[r][i];
                                        number++;
                                    }
                                }else if(number==2){    //第3次出现空位
                                    if(chessArray[r][i]==chessArray[r][i-1]){
                                        break;
                                    }
                                }
                            }else { //该位位棋子
                                if(chess==0){
                                    chess = chessArray[r][i];
                                    code = code +chessArray[r][i];
                                }else if(chess==chessArray[r][i]){
                                    code = code +chessArray[r][i];
                                }else {         //碰到不同颜色的棋子跳出循环
                                    code = code +chessArray[r][i];
                                    break;
                                }
                            }
                        }
                        System.out.print(code+" ");
                        Integer value1 = map.get(code); //Inter 整数类
                        if(value1!=null){
                            weightArray[r][c] += value1;
                        }
                        //垂直方向
                        code = "0";
                        chess = 0;
                        number=0;
                        //垂直向上
                        for(int i=r-1;i>=0;i--){
                            if(chessArray[i][c]==0){
                                if(r==i+1){
                                    break;      //连续2个空位跳出循环
                                }else if(number==0){    //第一次出现空位
                                    code = code +chessArray[i][c];
                                    number++;
                                }else if(number==1){//第2次出现空位
                                    if(chessArray[i][c]==chessArray[i+1][c]){
                                        break;
                                    }else {
                                        code = code +chessArray[i][c];
                                        number++;
                                    }
                                }else if(number==2){//第3次出现空位
                                    if(chessArray[i][c]==chessArray[i+1][c]){
                                        break;
                                    }
                                }
                            }else {
                                if(chess==0){
                                    chess = chessArray[i][c];
                                    code = code +chessArray[i][c];
                                }else if(chess==chessArray[i][c]){
                                    code = code +chessArray[i][c];
                                }else {
                                    code = code +chessArray[i][c];
                                    break;
                                }
                            }
                        }
                        System.out.print(code+" ");
                        Integer value2 = map.get(code); //Inter 整数类
                        if(value2!=null){
                            weightArray[r][c] += value2;
                        }
                        code = "0";
                        chess = 0;
                        number=0;
                        //垂直向下
                        for(int i=r+1;i<ROW;i++){
                            if(chessArray[i][c]==0){
                                if(r==i-1){
                                    break;
                                }else if(number==0){
                                    code = code +chessArray[i][c];
                                    number++;
                                }else if(number==1){
                                    if(chessArray[i][c]==chessArray[i-1][c]){
                                        break;
                                    }else {
                                        code = code +chessArray[i][c];
                                    }
                                }else if(number==2){
                                    if(chessArray[i][c]==chessArray[i-1][c]){
                                        break;
                                    }
                                }
                            }else {
                                if(chess==0){
                                    chess = chessArray[i][c];
                                    code = code +chessArray[i][c];
                                }else if(chess==chessArray[i][c]){
                                    code = code +chessArray[i][c];
                                }else {
                                    code = code +chessArray[i][c]; 
                                    break;
                                }
                            }
                        }
                        Integer value3 = map.get(code); //Inter 整数类
                        if(value3!=null){
                            weightArray[r][c] += value3;
//                      }
                        //左斜
                        code = "0";
                        chess = 0;
                        number=0;
                        //往左上
                        int i,j;
                        for(i=r-1,j=c-1;i>=0&&j>=0;i--,j--){
                            if(chessArray[i][j]==0){
                                if(r==i+1&&c==j+1){
                                    break;
                                }else if(number==0){
                                    code = code +chessArray[i][j];
                                    number++;
                                }else if(number==1){
                                    if(chessArray[i][j]==chessArray[i+1][j+1]){
                                        break;
                                    }else {
                                        code = code +chessArray[i][j];
                                        number++;
                                    }
                                }else if(number==2){
                                    if(chessArray[i][j]==chessArray[i+1][j+1]){
                                        break;
                                    }
                                }
                            }else {
                                if(chess==0){
                                    chess=chessArray[i][j];
                                    code = code +chessArray[i][j];
                                }else if(chess==chessArray[i][j]){
                                    code = code +chessArray[i][j];
                                }else {
                                    code = code +chessArray[i][j];
                                    break;
                                }
                            }
                        }
                        System.out.println(code+" ");
                        Integer value4 = map.get(code); //Inter 整数类
                        if(value4!=null){
                            weightArray[r][c] += value4;
                        }
                        code = "0";
                        chess = 0;
                        number = 0;
                        //往右下
                        for(i=r+1,j=c+1;i<ROW&&j<COLUM;i++,j++){
                            if(chessArray[i][j]==0){
                                if(r==i-1&&c==j-1){
                                    break;
                                }else if(number==0){
                                    code = code +chessArray[i][j];
                                    number++;
                                }else if(number==1){
                                    if(chessArray[i][j]==chessArray[i-1][j-1]){
                                        break;
                                    }else {
                                        code = code +chessArray[i][j];
                                        number++;
                                    }
                                }else if(number==2){
                                    if(chessArray[i][j]==chessArray[i-1][j-1]){
                                        break;
                                    }
                                }
                            }else {
                                if(chess==0){
                                    chess = chessArray[i][j];
                                    code = code +chessArray[i][j];
                                }else if(chess==chessArray[i][j]){
                                    code = code +chessArray[i][j];
                                }else {
                                    code = code +chessArray[i][j];
                                    break;
                                }
                            }
                        }
                        System.out.println(code+" ");
                        Integer value5 = map.get(code); //Inter 整数类
                        if(value5!=null){
                            weightArray[r][c] += value5;
                        }
                        //右斜
                        code = "0";
                        chess = 0;
                        number = 0;
                        //往左
                        for(i=r+1,j=c-1;i<ROW&&j>=0;i++,j--){
                            if(chessArray[i][j]==0){
                                if(r==i-1&&c==j+1){
                                    break;
                                }else if(number==0){
                                    code = code +chessArray[i][j];
                                    number++;
                                }else if(number==1){
                                    if(chessArray[i][j]==chessArray[i-1][j+1]){
                                        break;
                                    }else {
                                        code = code +chessArray[i][j];
                                        number++;
                                    }
                                }else if(number==2){
                                    if(chessArray[i][j]==chessArray[i-1][j+1]){
                                        break;
                                    }
                                }
                            }else {
                                if(chess==0){
                                    chess=chessArray[i][j];
                                    code = code +chessArray[i][j];
                                }else if(chess==chessArray[i][j]){
                                    code = code +chessArray[i][j];
                                }else {
                                    code = code +chessArray[i][j];
                                    break;
                                }
                            }
                        }
                        System.out.println(code+" ");
                        Integer value6 = map.get(code); //Inter 整数类
                        if(value6!=null){
                            weightArray[r][c] += value6;
                        }
                        //往右
                        code = "0";
                        chess = 0;
                        number = 0;
                        for(i=r-1,j=c+1;i>=0&&j<COLUM;i--,j++){
                            if(chessArray[i][j]==0){
                                if(r==i+1&&c==j-1){
                                    break;
                                }else if(number==0){
                                    code = code +chessArray[i][j];
                                    number++;
                                }else if(number==1){
                                    if(chessArray[i][j]==chessArray[i+1][j-1]){
                                        break;
                                    }else {
                                        code = code +chessArray[i][j];
                                        number++;
                                    }
                                }else if(number==2){
                                    if(chessArray[i][j]==chessArray[i+1][j-1]){
                                        break;
                                    }
                                }
                            }else {
                                if(chess==0){
                                    chess=chessArray[i][j];
                                    code = code +chessArray[i][j];
                                }else if(chess==chessArray[i][j]){
                                    code = code +chessArray[i][j];
                                }else {
                                    code = code +chessArray[i][j];
                                    break;
                                }
                            }
                        }
                        System.out.println(code+" ");
                        Integer value7 = map.get(code); //Inter 整数类
                        if(value7!=null){
                            weightArray[r][c] += value7;
                        }
                }
            }
        }
    }

    }

}

猜你喜欢

转载自blog.csdn.net/A_D_I_D_A_S/article/details/81982777