五子棋(人人博弈和人机博弈的Java实现)

项目实现的功能

1、实现人与人对决。

2、实现人与机器对决,对局双方各执一色棋子,要求其中一方为机器。

3、游戏开始要求为空棋盘。

4、黑先、白后,交替下子,每次只能下一子。

5、棋子下在棋盘的空白点上,棋子下定后,不得向其它点移动,不得从棋盘上拿掉或拿起另落别处。

6、黑方的第一枚棋子可下在棋盘任意交叉点上。

7、直到有一方获胜,结束对局。

8、要有图形界面,且界面设计美观、交互性好

9、允许悔棋

项目实现效果图

部分效果实现思路

为了计算实现悔棋操作,定义了一个栈,用来记录每一步的棋子。

机器方AI类的定义,该类中使用到的数据结构有两个Map,分别为AttackMap,其中存放的是进攻棋型,以及棋型对应的权值;DefendMap存放的是防守棋型,以及棋型对应的权值。这两个Map中,棋型是key,权值是value。Ai会根据算法算出当前棋盘空白交叉的的权值,然后Ai会下在权值最大的位置。

Ai算法的逻辑

清空权值矩阵,判断是否是Ai的回合,获取一个点的所有棋链(即进攻棋链和防御棋链)。定义一个二维数组来存放棋盘所有点的权值,最后计算最佳下棋点。

写代码遇到的坑

Java在传参时,只能传引用类型(类类型,接口类型和数组),基本数据类型(byte,short,int,long,char,float,double,Boolean)在传参的时候没有改变实际参数。简单来说,如果想两个类共享一个属性,这个属性必须是引用类型,不能是基本数据类型。

完整代码

Chess类 

public class Chess {//记录每下一个棋子的状态
    private int row, col;
    private int color;
    public Chess(int row,int col,int color){
        this.row = row;
        this.col = col;
        this.color = color;
    }
    public Chess(){

    }
    public void setRow(int row) {
        this.row = row;
    }

    public void setCol(int col) {
        this.col = col;
    }

    public void setColor(int color) {
        this.color = color;
    }
    public int getRow() {
        return row;
    }

    public int getCol() {
        return col;
    }

    public int getColor() {
        return color;
    }
}

ChessListener类

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

public class ChessListener extends MouseAdapter implements ActionListener {
    public   final int  BOARD_SIZE = 13;
    // 定义棋盘数组
    public final int[][] board = new int[BOARD_SIZE][BOARD_SIZE];
    // 定义棋子的颜色,0表示无棋子,1表示黑子,2表示白子
    private  final int NONE = 0;
    private  final int BLACK = 1;
    private  final int WHITE = 2;
    // 定义当前轮到哪种颜色的棋子
    public int currentColor = BLACK;
    public BoardPanel  boardpanel;
    public Graphics g ;
    public GameReview gameReview=new GameReview();
    public int idex=0;
    public FiveChess reboard ;
    public boolean isregret = true;
    public boolean isPVE = true;
    public boolean aifirst=false;
    public  Ai  ai = new Ai();

    public void setBoardPanel(BoardPanel  boardpanel){//通过棋子的动态数组修改棋局
        this.boardpanel=boardpanel;

    }
    public void actionPerformed(ActionEvent e) {
        JButton jButton = (JButton) e.getSource();
        if (jButton.getActionCommand().equals("悔棋")&&isregret) {
//            for (Chess c : gameReview.chesses) {
//                System.out.println("要回其的列" + c.getCol());
//            }
            Chess chess1 = gameReview.chesses.get(gameReview.chesses.size() - 1);
            gameReview.chesses.remove(gameReview.chesses.size() - 1);
            board[chess1.getRow()][chess1.getCol()] = NONE;
            Chess chess2 = gameReview.chesses.get(gameReview.chesses.size() - 1);
            gameReview.chesses.remove(gameReview.chesses.size() - 1);
            board[chess2.getRow()][chess2.getCol()] = NONE;
            boardpanel.repaint();
        } else if (jButton.getActionCommand().equals("再来一局")) {
            boardpanel.resetBoard();
            gameReview.allclear();
            boardpanel.repaint();
            idex=0;//指针也要重新归零
            System.out.println(jButton.getActionCommand());
        } else if (jButton.getActionCommand().equals("人人对战")) {
            isPVE = false;
        } else if (jButton.getActionCommand().equals("人机对战")) {
            isPVE = true;
        }else if (jButton.getActionCommand().equals("你先手")) {
            isPVE = true;
        }else if (jButton.getActionCommand().equals("AI先手")&&!aifirst) {
            Chess chess = new Chess(BOARD_SIZE/2,BOARD_SIZE/2,WHITE);
            gameReview.chesses.add(chess);
            board[chess.getRow()][chess.getCol()]=WHITE;
            System.out.println("ai下中间了");
            boardpanel.repaint();
            aifirst=true;
        }
        else if (jButton.getActionCommand().equals("复盘")) {
            boardpanel.resetBoard();
            isregret=false;
            System.out.println(jButton.getActionCommand());
            boardpanel.repaint();
//            FiveChess reboard = new FiveChess();
//            for (Component component : reboard.getComponents()) {
//                if (component instanceof JButton) {
//                    JButton button = (JButton) component;
//                    if (button.getActionCommand().equals("悔棋")||button.getActionCommand().equals("人人对战")||button.getActionCommand().equals("人机对战")) {
//                        reboard.remove(button);
//                    }
//                }
//            }
        } else if (jButton.getActionCommand().equals("复盘上一步")) {
            if (idex >0) {
                Chess chess1 = gameReview.chesses.get(--idex);
                board[chess1.getRow()][chess1.getCol()] = NONE;
                boardpanel.repaint();
            }
            System.out.println(jButton.getActionCommand());
        } else if (jButton.getActionCommand().equals("复盘下一步")) {
            if (idex < gameReview.chesses.size()) {
                Chess chess3 = gameReview.chesses.get(idex++);
                if (chess3.getColor() == BLACK) {
                    board[chess3.getRow()][chess3.getCol()] = BLACK;
                    System.out.println(jButton.getActionCommand());
                } else {
                    board[chess3.getRow()][chess3.getCol()] = WHITE;
                }
                boardpanel.repaint();
            }
            else{
                JOptionPane.showMessageDialog(boardpanel, "复盘结束!");
            }
        }
    }
    public void mouseReleased (MouseEvent e) {
    // 重绘棋盘面板
    // 获取鼠标点击的坐标
    int x = e.getX();
    int y = e.getY();
    int row=0;
    int col=0;
    aifirst=true;
    // 将坐标转换为棋盘数组的索引
    if(((y - 15) % 30)>=15) {
        row = ((y - 15) / 30)+1;
        System.out.println("row:"+row);
    }
    else if(((y - 15) % 30)<15) {
        row = ((y - 15) / 30);
        System.out.println(row);
    }
    if(((x- 15) % 30)>=15) {
        col = ((x - 15) / 30)+1;
        System.out.println(col);
    }
    else if(((x- 15) % 30)<15) {
        col = ((x - 15) / 30);
    }
        //boardpanel.repaint();
    // 判断是否在棋盘范围内并且该位置没有棋子
    if (row >= 0 && row < BOARD_SIZE && col >= 0 && col < BOARD_SIZE && board[row][col] == NONE) {
        // 在该位置放置当前颜色的棋子
        board[row][col] = currentColor;
        boardpanel.repaint();
        boardpanel.validate();
        Chess chess;
        if(currentColor==1){
            chess = new Chess(row, col, BLACK);
            //System.out.println("chess=:"+chess.getRow()+"和"+chess.getCol());
        }
        else{
            chess = new Chess(row, col, WHITE);
        }
        gameReview.chesses.add(chess);
        //System.out.println(currentColor);
        // 判断是否有五子连珠,即获胜
        if (boardpanel.isWin(row, col, currentColor)) {
            String colorName = currentColor == BLACK ? "黑" : "白";
            JOptionPane.showMessageDialog(boardpanel, colorName + "方获胜!");
        } else {
            if (!isPVE) {//如果模式是人人对战
                // 没有获胜则交换棋子颜色,继续下一轮
                currentColor = currentColor == BLACK ? WHITE : BLACK;
                boardpanel.currentColor = currentColor;
                if (currentColor == BLACK) {
                    System.out.println("下一个:黑方");
                } else {
                    System.out.println("下一个:白方");
                }
                // 更新状态栏显示
                boardpanel.updateStatusBar();
            }
            else{
                Ai.board =boardpanel.board;
                Ai.gameReview=gameReview;
                Ai.AiPlay();
                //boardpanel.board = Ai.board;
                boardpanel.repaint();
            }
        }
    }

}
}

BoardPanel类

import javax.swing.*;
import java.awt.*;

// 定义内部类表示棋盘和棋子,继承自JPanel
public  class BoardPanel extends JPanel {
    public final int  BOARD_SIZE = 13;
    // 定义棋盘数组
    public  int[][] board = new int[BOARD_SIZE][BOARD_SIZE];
    // 定义棋子的颜色,0表示无棋子,1表示黑子,2表示白子
    private  final int NONE = 0;
    private  final int BLACK = 1;
    private  final int WHITE = 2;
    // 定义当前轮到哪种颜色的棋子
    public  int currentColor=BLACK;
    // 定义状态栏
    public  JLabel statusBar=new JLabel();

    public BoardPanel() {
        super();
        setLayout(new BorderLayout());
        // 初始化棋盘数组为全0
        for (int i = 0; i < BOARD_SIZE; i++) {
            for (int j = 0; j < BOARD_SIZE; j++) {
                board[i][j] = NONE;
            }
        }
    }
        //重写JPanel的paintComponent方法
        public void paint(Graphics g) {
            super.paint(g);
        // 设置背景颜色
        setBackground(Color.GRAY);
        // 设置画笔颜色为黑色
        g.setColor(Color.BLACK);
        // 画15条横线和竖线来形成棋盘网格
        for (int i = 0; i < BOARD_SIZE; i++) {
            g.drawLine(15, 15 + i * 30, 15 + (BOARD_SIZE - 1) * 30, 15 + i * 30);
            g.drawLine(15 + i * 30, 15, 15 + i * 30, 15 + (BOARD_SIZE - 1) * 30);
        }
        // 遍历棋盘数组,画出相应颜色的棋子
        for (int i = 0; i < BOARD_SIZE; i++) {
            for (int j = 0; j < BOARD_SIZE; j++) {
                if (board[i][j] == BLACK) {
                    g.setColor(Color.BLACK);
                    g.fillOval(5 + j * 30, 5 + i * 30, 20, 20);
                } else if (board[i][j] == WHITE) {
                    g.setColor(Color.WHITE);
                    g.fillOval(5 + j * 30, 5 + i * 30, 20, 20);
                }
            }
        }
            this.updateStatusBar();
    }
        // 判断是否有五子连珠的方法,参数为最后一步下的棋子的位置和颜色
        public boolean isWin(int row, int col, int color) {
            // 定义四个方向的增量数组,分别表示水平,垂直,左上右下,右上左下
            int[][] directions = {{1, 0}, {0, 1}, {1, 1}, {1, -1}};
            // 遍历四个方向
            for (int[] direction : directions) {
                // 计算该方向上连续同色棋子的个数
                int count = 1;
                int x = col;
                int y = row;
                // 往该方向前进,直到遇到边界或者不同色的棋子,累加计数器
                while (true) {
                    x += direction[0];
                    y += direction[1];
                    if (x < 0 || x >= BOARD_SIZE || y < 0 || y >= BOARD_SIZE || board[y][x] != color) {
                        break;
                    }
                    count++;
                }
                // 往该方向后退,直到遇到边界或者不同色的棋子,累加计数器
                x = col;
                y = row;
                while (true) {
                    x -= direction[0];
                    y -= direction[1];
                    if (x < 0 || x >= BOARD_SIZE || y < 0 || y >= BOARD_SIZE || board[y][x] != color) {
                        break;
                    }
                    count++;
                }
                // 如果计数器达到5,表示有五子连珠,返回true
                if (count >= 5) {
                    return true;
                }
            }
            // 如果四个方向都没有五子连珠,返回false
            return false;
        }

        // 重置棋盘的方法,将棋盘数组全部置为0,将棋子颜色重置为黑色,并更新状态栏
        public void resetBoard() {
            for (int i = 0; i < BOARD_SIZE; i++) {
                for (int j = 0; j < BOARD_SIZE; j++) {
                    board[i][j] = NONE;
                }
            }
            this.currentColor = BLACK;
            this.updateStatusBar();
        }
        // 更新状态栏的方法,根据当前轮到的棋子颜色显示相应的文本
        public void updateStatusBar() {
            String colorName = this.currentColor == BLACK ? "黑" : "白";
            statusBar.setText("轮到" + colorName + "方下棋");
        }
}

GameReview类

import java.util.ArrayList;

public class GameReview {//有最终胜利的棋局,有各个棋子下的顺序
    public ArrayList<Chess> chesses = new ArrayList<>();
    private BoardPanel  boardpanel;

    public void remove(){
        chesses.remove(chesses.size()-1);
        chesses.remove(chesses.size()-1);
        boardpanel.repaint();
    }
    public void allclear(){//清空动态数组的所有元素
        chesses.clear();
    }
}

Ai类 

import javax.swing.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class Ai {
    private static Map<String,Integer> AttackMap=new HashMap<>();
    private static Map<String,Integer> DefendMap=new HashMap<>();
    public static final int  board_size = 13;
    // 定义棋盘数组
    private static Boolean aiTurn=true;   //该值用来判断是否为ai的回合,所以初值为true
    private static final int NONE = 0;
    private static final int BLACK = 1;
    private static final int WHITE = 2;
    public static int aicolor=WHITE;
    public static int pcolor=BLACK;
    public static int[][] board = new int[board_size][board_size];
    public static int[][] valuePad = new int[board_size][board_size]; //棋盘的权值矩阵,用来记录每一个位置的权值
    public static BoardPanel  boardpanel;
    public static GameReview gameReview = new GameReview();

    static {
        //还要重新设计赋分策略,才能保证五子棋机器人的准确判断
        //因为已经固定了 *为黑子,且默认将机器人设为黑方,所以机器人只能是黑方
        //还要设置防守方的数值,防止被gank掉
        //右边put的map值,是防守分数,这样Ai就不会一味的猛冲

        //左边:进攻棋链,权值越大说明该棋链越接近胜利   右边:防御棋链,权值越大说明该棋链约值得防御
        AttackMap.put("*****",   100000);//连五
        /*                                 */DefendMap.put("ooooo",   30000);
        AttackMap.put("-****-",   5000);//活四
        /*                                 */DefendMap.put("-oooo-",   3000);
        AttackMap.put("*-***",   700);//冲四  1
        /*                                 */DefendMap.put("o-ooo",   150);
        AttackMap.put("***-*",   700);//冲四  1  反向
        /*                                 */DefendMap.put("ooo-o",   150);
        AttackMap.put("-****o",   1000);//冲四  2
        /*                                 */DefendMap.put("-oooo*",   200);
        AttackMap.put("o****-",   1000);//冲四  2  反向
        /*                                 */DefendMap.put("*oooo-",  200);
        AttackMap.put("**-**",   700);//冲四   3
        /*                                 */DefendMap.put("oo-oo",  200);
        AttackMap.put("-***-",   500);//活三   1
        /*                                 */DefendMap.put("-ooo-",  100);
        AttackMap.put("*-**",   150);//活三  2
        /*                                 */DefendMap.put("o-oo",  50);
        AttackMap.put("**-*",   150);//活三  2   反向
        /*                                 */DefendMap.put("oo-o",  50);
        AttackMap.put("--***o",   100);//眠三  1
        /*                                 */DefendMap.put("--ooo*",  20);
        AttackMap.put("o***--",   100);//眠三  1  反向
        /*                                 */DefendMap.put("*ooo--",  20);
        AttackMap.put("-*-**o",   80);//眠三   2
        /*                                 */DefendMap.put("-o-oo*",  15);
        AttackMap.put("o**-*-",   80);//眠三   2  反向
        /*                                 */DefendMap.put("*oo-o-",  15);
        AttackMap.put("-**-*o",   60);//眠三   3
        /*                                 */DefendMap.put("-oo-o*",  10);
        AttackMap.put("o*-**-",   60);//眠三   3   反向
        /*                                 */DefendMap.put("*o-oo-",  10);
        AttackMap.put("*--**",   60);//眠三   4
        /*                                 */DefendMap.put("o--oo",  10);
        AttackMap.put("**--*",   60);//眠三   4   反向
        /*                                 */DefendMap.put("oo--o",  10);
        AttackMap.put("*-*-*",   60);//眠三   5
        /*                                 */DefendMap.put("o-o-o",  10);
        AttackMap.put("o-***-o",   60);//眠三   6
        /*                                 */DefendMap.put("*-ooo-*",  2);
        AttackMap.put("--**--",   50);//活二  1
        /*                                 */DefendMap.put("--oo--",  2);
        AttackMap.put("-*-*-",   20);//活二   2
        /*                                 */DefendMap.put("-o-o-",  2);
        AttackMap.put("*--*",   20);//活二   3
        /*                                 */DefendMap.put("o--o",   2);
        AttackMap.put("---**o",   10);//眠二  1
        /*                                 */DefendMap.put("---oo*",   1);
        AttackMap.put("o**---",   10);//眠二  1   反向
        /*                                 */DefendMap.put("*oo---",   1);
        AttackMap.put("--*-*o",   10);//眠二  2
        /*                                 */DefendMap.put("--o-o*",   1 );
        AttackMap.put("o*-*--",   10);//眠二  2   反向
        /*                                 */DefendMap.put("*o-o--",   1);
        AttackMap.put("-*--*o",   10);//眠二  3
        /*                                 */DefendMap.put("-o--o*",   1);
        AttackMap.put("o*--*-",   10);//眠二  3   反向
        /*                                 */DefendMap.put("*o--o-",   1);
        AttackMap.put("*---*",   10);//眠二  4
        /*                                 */DefendMap.put("o---o",   1);
    }

    //Ai下棋主流程
    public static void AiPlay(){
        //清空权值矩阵,避免前一回合影响本回合的判断
        clearvaluePad();

        //判断是否为人机回合,AI永远下黑棋
//        if (!aiTurn){
//            return;
//        }

        Chess bestaichess=new Chess();
        if(isEmptyPad()){
            //如果是空棋盘,则永远下中间点的位置,
             bestaichess = new Chess(board_size/2,board_size/2,aicolor);
             gameReview.chesses.add(bestaichess);
             putChess(bestaichess);
            System.out.println(Arrays.deepToString(board));
             System.out.println("AI下中间");
             boardpanel.repaint();
        }
        else {
            //先计算防御棋链,看看当前棋局是否有需要防御的地方
            boolean defend=false;
//            for (int i=0;i<board_size;i++){
//                for (int j=0;j<board_size;j++){
//                    ArrayList<String> defends = getPositionChessLink(i, j, "defend");
//                    for (String s : defends) {
//                        if (s.equals("ooooo")){
//                            System.out.println("防御");
//                            bestaichess=new Chess(i,j,aicolor);
//                            defend=true;
//                            break ;
//                        }
//                    }
//                }
//            }
            if (!defend){
                //计算整个棋盘的权值
                getAllValue();
                //选取最佳下棋位置
                bestaichess = getBestaichess();
                gameReview.chesses.add(bestaichess);
                System.out.println("最佳位置的行"+bestaichess.getRow()+"最佳位置的列"+bestaichess.getCol());
            }
        }
        //将棋下入颜色棋盘
        putChess(bestaichess);
        //判断AI是否胜利
        if (boardpanel.isWin(bestaichess.getRow(), bestaichess.getCol(), WHITE)) {
            //String colorName = currentColor == BLACK ? "黑" : "白";
            JOptionPane.showMessageDialog(boardpanel, "AI获胜!");
        }
    }
    public static void AiPlayText(){
        board[0][0]=WHITE;
        board[0][1]=WHITE;
    }
    public static void clearvaluePad(){
        for (int i = 0; i < board_size; i++) {
            for (int j = 0; j < board_size ;j++) {
                valuePad[i][j]=-1;
            }
        }
    }

    /**
     * 该方法实现Ai的下棋操作,传入的Position对象 坐标为行列坐标
     * @param
     */
    public static void putChess(Chess p){
        //System.out.println("哈哈,这就是最佳位置");
        //更改颜色矩阵,完成下棋操作
            board[p.getRow()][p.getCol()] = aicolor;
    }
    /**
     * 该方法啊实现选取权值最大的点,AI下的棋就是下在这个点上
     * @return  返回的是一个行列坐标的position对象
     */
    public static Chess getBestaichess(){
        //遍历权值棋盘,找出权值最大的点
        int max=-1;
        Chess position=new Chess();
        for(int i = 0; i<board_size; i++){
            for (int j = 0; j < board_size; j++){
                //判断该点的权值是否大于最大值,同时该点必须为空棋
                if(valuePad[i][j] > max){
                    max = valuePad[i][j];
                    position.setRow(i);
                    position.setCol(j);
                }
            }
        }
        position.setColor(aicolor);
         return position;
//         //  //遍历找出所有的最大权值点
//        List<Position> allMaxPosition=new ArrayList<>();
//
//        for(int i=0;i<size;i++){
//            for (int j=0;j<size;j++){
//                //判断该点的权值是否大于最大值,同时该点必须为空棋
//                if(colorPad[i][j]==ChessColor.Blank&&valuePad[i][j]==max){
//                    allMaxPosition.add(new Position(i,j));
//                }
//            }
//        }
//        //在最大权值点列表种,随机取出一个点(随机取的原因是:遍历数组都是按固定顺序遍历的,若不采取随机取的方法,则玩家能够通过固定的套路取胜)
//        int s=allMaxPosition.size()-1;
//        return allMaxPosition.get((int)(Math.random()*s));
    }

    /**
     * 为整个权值棋盘,赋值
     */
    public static void getAllValue(){
        //获取权值棋盘
//        int[][] valuePad = ChessPad.valuePad;
//        int size = ChessPad.size;
        for (int i=0;i<board_size;i++){
            for (int j = 0; j < board_size; j++) {
                //将每一个点传入计算权值
                valuePad[i][j]=CalculateValue(i,j);
            }
        }
    }
//    public static int getPositionDefendValue(int row , int col){
//        ArrayList<String> defendList = getPositionChessLink(row,col,"defend");
//
//        //计算权值
//        int defendValue=0;
//
//        for (String s : defendList) {
//            if(DefendMap.containsKey(s)){
//                defendValue+=DefendMap.get(s);
//            }
//        }
//
//        return defendValue;
//    }

    /**
     * 该方法实现计算传入点的权值
     */
    public static int CalculateValue(int row,int col){
        //调用方法,返回该点的棋链
        ArrayList<String> attackList = getPositionChessLink(row,col,"attack");
        ArrayList<String> defendList = getPositionChessLink(row,col,"defend");

        //计算权值
        int attackValue=0;
        int defendValue=0;
        for (String s : attackList) {
            if(AttackMap.containsKey(s)){
                attackValue+=AttackMap.get(s);
            }
        }

        for (String s : defendList) {
            if(DefendMap.containsKey(s)){
                defendValue+=DefendMap.get(s);
            }
        }

        return Math.abs(attackValue-defendValue);  //值越大说明该点即适合防御又适合进攻
    }

    /**
     * 该方法实现获取一个点的所有棋链
     *  棋链的获取分为四个方向:横、竖、斜、反斜
     */
    public static ArrayList<String> getPositionChessLink(int row,int col,String type){

        boolean flag=false;//flag为临时下的棋的标注
        if(board[row][col]==NONE&&type.equals("attack")){
            //假设该空点下的棋为黑棋
            board[row][col]=aicolor;
            flag=true;
        }
        else if(board[row][col]==NONE&&type.equals("defend")){
                board[row][col]=pcolor;
            flag=true;
        }

        ArrayList<String> resultList=new ArrayList<>();
//       System.out.println("竖方向:");
        if(flag) {
            //先从竖方向获取棋链
            for (int i = 4; i <= 7; i++) {  //先寻找棋链长度最短为4 最后寻找最长不超过7
                for (int j = 0; j < i; j++) {    //判断传入的棋子在棋链上的位置(即第几个棋子,从左向右数)
                    String s = "";               //初始化
                    int startRow = row - j;   //计算竖方向的开始坐标
                    int endRow = startRow + i - 1;   //计算竖方向的结束坐标
                    //此处需要判断开始的点和结束的点是否超出了棋盘
                    if (startRow < 0 || endRow >= board_size) {
                        //该点超过了棋盘的范围
                        continue;
                    }
                    for (; startRow <= endRow; startRow++) {
                        if (board[startRow][col] == NONE) {
                            s = s + "-";
                        } else if (board[startRow][col] == aicolor) {
                            s = s + "*";
                        } else {
                            s = s + "o";
                        }
                    }
//               System.out.println(s);
                    resultList.add(s);       //将该棋链加入结果列表
                }
            }
//       System.out.println("横方向:");
            //计算横方向的棋链权值
            for (int i = 4; i <= 7; i++) {  //棋链长度,最短4,最长7

                for (int j = 0; j < i; j++) {    //棋在棋链上的位置,(从上往下)

                    String s = "";

                    //由于是横方向,故只需要计算开始的y和结束的y坐标
                    int startCol = col - j;
                    int endCol = startCol + i - 1;

                    //判断开始位置和结束位置是否在棋盘范围内
                    if (startCol < 0 || endCol >= board_size) {
                        continue;
                    }

                    for (; startCol <= endCol; startCol++) {
                        if (board[row][startCol] == NONE) {
                            s = s + "-";
                        } else if (board[row][startCol] == aicolor) {
                            s = s + "*";
                        } else {
                            s = s + "o";
                        }
                    }

//               System.out.println(s);
                    resultList.add(s);
                }
            }

//       System.out.println("斜方向:");
            //从斜方向获取棋链
            for (int i = 4; i <= 7; i++) {

                for (int j = 0; j < i; j++) {

                    //此处为斜方向,改变棋在棋链上的位置,涉及 x 和 y 两个方向的改变,从左下往右上的方向来计算 两个坐标的变化为
                    int startRow = row + j;
                    int startCol = col - j;

                    int endRow = startRow - i + 1;
                    int endCol = startCol + i - 1;

                    //判断开始点和结束点是否在棋盘内
                    if (!((startRow >= 0 && startRow < board_size && startCol >= 0 && startCol < board_size) && (endRow >= 0 &&
                            endRow < board_size && endCol >= 0 && endCol < board_size))) {
                        continue;
                    }

                    String s = "";

                    for (int _row = startRow, _col = startCol;
                         _row >= endRow && _col <= endCol;
                         _row--, _col++) {

                        if (board[_row][_col] == NONE) {
                            s = s + "-";
                        } else if (board[_row][_col] == aicolor) {
                            s = s + "*";
                        } else {
                            s = s + "o";
                        }
                    }

//               System.out.println(s);
                    resultList.add(s);
                }
            }

//       System.out.println("反斜方向:");
            //反斜方向
            for (int i = 4; i <= 7; i++) {
                for (int j = 0; j < i; j++) {

                    //计算开始的点
                    int startRow = row - j;
                    int startCol = col - j;

                    int endRow = startRow + i - 1;
                    int endCol = startCol + i - 1;

                    String s = "";

                    if (!((startRow >= 0 && startRow < board_size && startCol >= 0 && startCol < board_size) &&
                            (endRow >= 0 && endRow < board_size && endCol >= 0 && endCol < board_size))) {
                        continue;
                    }

                    for (int _row = startRow, _col = startCol; _row <= endRow && _col <= endCol; _row++, _col++) {
                        if (board[_row][_col] == NONE) {
                            s = s + "-";
                        } else if (board[_row][_col] == aicolor) {
                            s = s + "*";
                        } else {
                            s = s + "o";
                        }
                    }

//               System.out.println(s);
                    resultList.add(s);
                }
            }
        }
        //返回之前将临时下的棋恢复
        if (flag){
            board[row][col]=NONE;
        }
        return resultList;
    }

    /**
     * 该方法用于判断棋盘是不是都为空
     * @return
     */
    public static boolean isEmptyPad(){
            for (int i=0;i<board_size;i++) {
                for(int j=0;j<board_size;j++){
                    if(!(board[i][j]==NONE)) return false;
                }
            }
        return true;
    }

}

主类FiveChess

import javax.swing.*;
import java.awt.*;

 public class FiveChess extends JFrame {
     public FiveChess(){
        // 创建状态栏并设置初始文本
         BoardPanel boardpanel =new BoardPanel();
         setTitle("五子棋");
         //设置初始化文本
         boardpanel.updateStatusBar();
        // 将棋盘面板和状态栏添加到窗口中
        add(boardpanel, BorderLayout.CENTER);
        add(boardpanel.statusBar,BorderLayout.SOUTH);
        Box select = Box.createVerticalBox();
         ChessListener listenner = new ChessListener();
         listenner.reboard=this;
        select.setPreferredSize(new Dimension(180,500));
         String[] button = {"再来一局","人人对战","人机对战","你先手","AI先手","悔棋","复盘","复盘上一步","复盘下一步"};//创建按钮数组
         for(int i=0;i<button.length;i++) {
             JButton jbu = new JButton(button[i]);//创建按钮对象,并赋给其数组值
             jbu.setPreferredSize(new Dimension(160,110));//设置按钮大小
             jbu.setActionCommand(button[i]);
             select.add(jbu);//给操控面板添加按钮组件
             jbu.addActionListener(listenner);//给按钮添加鼠标监听器

         }
         add(select,BorderLayout.EAST);
        // 设置窗口大小和位置,并显示
        setSize(650, 500);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         // 创建棋盘面板并添加鼠标监听器
         listenner.setBoardPanel(boardpanel);
         listenner.g=boardpanel.getGraphics();
         boardpanel.addMouseListener(listenner);
         listenner.boardpanel=boardpanel;
         Ai.boardpanel = boardpanel;
         boardpanel.board =listenner.board;
        // boardpanel.currentColor =listenner.currentColor;这么写没用
         setVisible(true);
    }
    public static void main(String[] args) {
           FiveChess newFivechess= new FiveChess();
    }

}

  • 5
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值