最近又回忆了棋魂,学了点围棋,于是写了个围棋的算法,一开始以为蛮简单的,结果还是写了半天
直接上代码
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;
}
}
}
}