源码链接:https://download.csdn.net/download/w2180z/12526532
基本规则
围棋的规则:棋盘19X19,黑子181颗,白子180颗,棋子临近的格子为它的气,连载一起的同色的棋子共享气,无气则死子,从棋盘上移除,死气的地方无法落子(若落子会造成敌方子死气则可以落在死气点):
算法思路
棋子的属性:
//邻居标记
private String tab;
//棋子所在点
private Point point;
//1 黑 2 白 0空
private int value;
棋盘定义,一个19X19的棋子数组,初始化时所有棋子value设置为0
//棋盘初始化
Qizi[][] qipan = new Qizi[19][19];
for (int i = 0; i < qipan.length; i++) {
for (int j = 0; j < qipan[i].length; j++) {
qipan[i][j] = new Qizi(i, j, 0);
}
}
基于围棋的规则,我们应该定义一个map,用于存放相邻的棋子list,他们拥有共同的邻居标记(类似于id);
另外,需要定义一个气的map,它的key是邻居标记(这里的邻居标记是和上一步定义的邻居标记关联的),value是所有气的集合,为了保证气的唯一性,我把气的坐标转换为string,存放在set中;
private Map<String,Set<String>> qiMap = null;
//邻居子map
private Map<String,List<Qizi>> linjuMap = null;
核心算法:
落子时,循环周围同色的邻居,如果该子周围没有同色的棋子,则这个棋子是一个独立的邻居组,新建邻居组赋予唯一的邻居标记,并标记该棋子的所属邻居组,计算该子的气;如果有相同颜色的棋子,那么把这个棋子添加到相同颜色棋子的邻居组中,重新计算该组的气,多个同色棋子可能涉及到多个邻居组和气的合并,这里需要注意不要重复合并。
判断计算后的气集合,如果是空,则标记死气(这里暂时不移除棋子,因为还需要判断异色棋子的气)
循环周围异色的邻居,计算异色邻居的气,如果异色邻居的气味空,那么需要提子,同时移除之前设置的死气标记(对应规则:若落子会造成敌方子死气则可以落在死气点),移除异色棋子的邻居组所有棋子,并且需要循环该异色棋子的相邻棋子,为他们添加气(移除的棋子点,为新的气点);这里需要注意避免重复移除的问题。
基于上面的思路,我们就可以实现围棋的基本算法
核心算法实现
private QipanUpdateListener qipanUpdateListener = null;
//邻居标记
private int tabIndex = 0;
public static final int WHITE = 2;
public static final int BLACK = 1;
public static final int KONGBAI = 0;
//回合数
private int huiheNum = 1;
//棋盘
private Qizi[][] qipan = null;
//默认黑子先手
private int zhiqiren = BLACK;
private int blackNum = 181;
private int whiteNum = 180;
/**
* @return the qipan
*/
public Qizi[][] getQipan() {
return qipan;
}
private Map<String,Set<String>> qiMap = null;
//邻居子map
private Map<String,List<Qizi>> linjuMap = null;
//变更棋手
private void tabQishou(){
if (zhiqiren == WHITE){
whiteNum--;
zhiqiren = BLACK;
}else {
zhiqiren = WHITE;
blackNum--;
}
//增加回合数
huiheNum++;
}
/**
* 下棋
* @param x 棋子坐标X
* @param y 棋子坐标Y
*/
public boolean add(int x,int y) {
//out range
if (x < 0 || x > 18 || y < 0 || y >