java 围棋算法 demo

最近又回忆了棋魂,学了点围棋,于是写了个围棋的算法,一开始以为蛮简单的,结果还是写了半天
在这里插入图片描述
在这里插入图片描述

直接上代码

package com.djx.test;

import java.util.Scanner;

/**
 * @author dengjx
 * @date 2022/3/29
 */
public class GoTest {

    static int black = 1;
    static int white = -1;

    /**
     * 棋盘定义
     */
    int len = 19;

    int[][] checkerboard = new int[len][len];

    /**
     * 白 落子 记录
     */
    int whiteIndex = 0;
    int[][] whiteRecord = new int[len * len][2];
    int[] whiteJie = new int[2];

    /**
     * 黑 落子 记录
     */
    int blackIndex = 0;
    int[][] blackRecord = new int[len * len][2];
    int[] blackJie = new int[2];

    {
        whiteJie[0] = -1;
        whiteJie[1] = -1;

        blackJie[0] = -1;
        blackJie[1] = -1;
    }

    /**
     * 落子
     * @param x 横坐标
     * @param y 纵坐标
     * @param piece 棋子
     */
    public boolean fallSeed(int x, int y, int piece) {

        // 不能下有子的位置
        if (checkerboard[x][y] != 0) {
            return false;
        }

        // 是否是不能下的劫
        if (hasForPre(x, y, piece)) {
            return false;
        }
        // 清除之前的劫财
        if (piece == white) {
            whiteJie[0] = -1;
            whiteJie[1] = -1;
        }

        if (piece == black) {
            blackJie[0] = -1;
            blackJie[1] = -1;
        }

        // 是否提子
        hasTiZi(x, y, piece);
        // 是否能落子
        // 提前落子
        checkerboard[x][y] = piece;
        if (getQi(x, y) > 0) {
            if (piece == white) {
                whiteRecord[whiteIndex][0] = x;
                whiteRecord[whiteIndex][1] = y;
                whiteIndex ++;
            }

            if (piece == black) {
                blackRecord[blackIndex][0] = x;
                blackRecord[blackIndex][1] = y;
                blackIndex ++;
            }
        } else {
            checkerboard[x][y] = 0;
            return false;
        }

        return true;
    }


    /**
     * 是否能提子
     * @param x 横坐标
     * @param y 纵坐标
     * @param piece 子
     * @return 是否
     */
    private boolean hasTiZi(int x, int y, int piece) {

        // 落子
        checkerboard[x][y] = piece;

        // 找到周围的相反的棋子 判断是否有气 没气则提掉
        boolean hasT = false;

        if (y > 0 && checkerboard[x][y - 1] == (piece == white?black:white)) {
            hasT = tiZi(x, y - 1, piece == white?black:white);
        }

        if (x > 0 && checkerboard[x - 1][y] == (piece == white?black:white)) {
            hasT = hasT || tiZi(x  - 1, y, piece == white?black:white);
        }

        if (y < len - 1 && checkerboard[x][y + 1] == (piece == white?black:white)) {
            hasT = hasT || tiZi(x, y + 1, piece == white?black:white);
        }

        if (x < len - 1 && checkerboard[x + 1][y] == (piece == white?black:white)) {
            hasT = hasT || tiZi(x + 1, y, piece == white?black:white);
        }

        checkerboard[x][y] = 0;

        return hasT;
    }

    /**
     * 深度优先搜索判断是否没气了, 没气就提掉
     * @param x 横坐标
     * @param y 纵坐标
     */
    private boolean tiZi(int x, int y, int piece) {

        // 创建一个记录遍历的棋盘 气的数量
        int[][] record = new int[len][len];

        // 从当前点开始进行深度优先搜索的判断
        int qi = findQi(x, y, record, piece);

        if (qi > 0) {
            return false;
        }

        // 删除记录的子 顺便查看是否是个劫
        int num = 0;
        for (int i = 0 ;i < record.length; i++) {

            for (int j = 0;j < record[i].length; j++) {

                if (record[i][j] == 1) {
                    checkerboard[i][j] = 0;
                    num++;
                    if (piece == white) {
                        whiteJie[0] = i;
                        whiteJie[1] = j;
                    }

                    if (piece == black) {
                        blackJie[0] = i;
                        blackJie[1] = j;
                    }
                }
            }
        }

        if (num > 1) {
            if (piece == white) {
                whiteJie[0] = -1;
                whiteJie[1] = -1;
            }

            if (piece == black) {
                blackJie[0] = -1;
                blackJie[1] = -1;
            }
        }

        return true;
    }

    private int findQi(int x, int y, int piece) {
        return findQi(x, y, new int[len][len], piece);
    }

    /**
     * 递归查询气的数量
     * @param x 横坐标
     * @param y 纵坐标
     * @param record 记录盘
     * @param piece 子
     * @return 气数量
     */
    private int findQi(int x, int y, int[][] record, int piece) {

        if (x < 0 || x >= len || y < 0 || y >= len || record[x][y] == 1) {
            return 0;
        }

        if (checkerboard[x][y] == 0 || checkerboard[x][y] == (piece == white?black:white)) {
            return 0;
        }

        // 记录
        record[x][y] = 1;

        // 获取气数量
        int qi = getQi(x, y);
;
        return qi + findQi(x - 1, y, record, piece) + findQi(x + 1, y, record, piece) + findQi(x, y - 1, record, piece) + findQi(x, y + 1, record, piece);
    }

    /**
     * 获取单个棋子周围的气
     */
    private int getQi(int x, int y) {

        int qi = 0;

        if (x - 1 >= 0 && y >= 0 && checkerboard[x - 1][y] == 0) {
            qi++;
        }

        if (x + 1 >= 0 && y >= 0 && checkerboard[x + 1][y] == 0) {
            qi++;
        }

        if (x >= 0 && y - 1 >= 0 && checkerboard[x][y - 1] == 0) {
            qi++;
        }

        if (x >= 0 && y + 1 >= 0 && checkerboard[x][y + 1] == 0) {
            qi++;
        }

        return qi;
    }


    /**
     * 是否是劫
     * @param x 横坐标
     * @param y 纵坐标
     * @param piece 子
     * @return 是否
     */
    private boolean hasForPre(int x, int y, int piece) {

        // 模拟落子是否有0气
//        checkerboard[x][y] = piece;
//        if (aroundNum(x, y, piece) != 0) {
//            checkerboard[x][y] = 0;
//            return false;
//        }
//        checkerboard[x][y] = 0;

        if (piece == white) {

            return whiteJie[0] == x && whiteJie[1] == y;
        }

        if (piece == black) {

            return blackJie[0] == x && blackJie[1] == y;
        }

        return false;
    }

    /**
     * 棋子周围同类棋子的数量
     */
    private int aroundNum(int x, int y, int piece) {

        int aroundNum = 0;

        if (x - 1 >= 0 && y >= 0 && checkerboard[x - 1][y] == piece) {
            aroundNum++;
        }

        if (x + 1 >= 0 && y >= 0 && checkerboard[x + 1][y] == piece) {
            aroundNum++;
        }

        if (x >= 0 && y - 1 >= 0 && checkerboard[x][y - 1] == piece) {
            aroundNum++;
        }

        if (x >= 0 && y + 1 >= 0 && checkerboard[x][y + 1] == piece) {
            aroundNum++;
        }

        return aroundNum;
    }

    public int[][] getCheckerboard() {
        return checkerboard;
    }

    /**
     * 打印棋盘
     */
    private void printCheckerboard() {
        System.out.print("   ");
        for (int i = 0;i < len; i++) {
            System.out.print("|");
            System.out.print((i+1) + (i >= 9?" ":"  "));
        }
        System.out.println("|");

        for (int i = 0 ;i < checkerboard.length; i++) {

            System.out.print((i+1) + (i >= 9?" ":"  "));
            System.out.print("|");
            for (int j = 0;j < checkerboard[i].length; j++) {

                if (checkerboard[i][j] == white) {
                    System.out.print(" ◯ ");
                }

                if (checkerboard[i][j] == black) {
                    System.out.print(" ● ");
                }

                if (checkerboard[i][j] == 0) {
                    System.out.print("   ");
                }
                System.out.print("|");
            }
            System.out.println();
        }
    }

    public static void main(String[] args) {

        Scanner scanner  = new Scanner(System.in);

        GoTest go = new GoTest();
        int zi = white;

        while (true) {
            zi = zi == white?black:white;
            System.out.print("当前执(" + (zi == white?"白":"黑") + "), 请下(格式为x,y):");

            try {
                String c =  scanner.next();
                String[] cs = c.split(",");

                int x = Integer.parseInt(cs[0]) - 1;
                int y = Integer.parseInt(cs[1]) - 1;

                if (!go.fallSeed(x, y, zi)) {
                    zi = zi == white?black:white;
                }
                go.printCheckerboard();
            } catch (Exception e) {
                e.printStackTrace();
                zi = zi == white?black:white;
            }
        }
    }


}

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值