我们以一个二位数组表示五子棋,通过x、y坐标,表示一个棋子的位置。
1、基本原理:
五子棋判断输赢,其实就是一个二维坐标上,判断上下、左右、两个45度直线,是否有五个相同的直连棋子。
2、判断时机:
一般情况下,我们可以通过遍历棋盘的每个点,从这个点出发,判断是否有五连子。但是实际上,我们并不需要这样做,因为我们在落子时,肯定当前其他地方没有五连子。我们要做的,就是从当前落子的位置判断,4个方向上是否有五连子。
3、算法实现:
private boolean checkByStep(Point p, List<Point> array, int xdiff, int ydiff) {
Point tmp = new Point(0, 0);
int i;
int cnt = 0;
//向反方向找到颜色相同的点
for (i = 1; i < 5; i++){
tmp.x = p.x - xdiff * i;
tmp.y = p.y - ydiff * i;
if (!array.contains(tmp))
break;
cnt++;
}
Log.e(TAG, "checkByStep: reverse cnt = " + cnt);
// Log.e(TAG, "checkByStep: reverse i = " + i + " begin (" + tmp.x + ", " + tmp.y + ")" + " diff = (" + xdiff + ", " + ydiff + ")");
int x = tmp.x;
int y = tmp.y;
for (i = 1; i < 5; i++){
tmp.x = p.x + xdiff * i;
tmp.y = p.y + ydiff * i;
if (!array.contains(tmp))
break;
cnt++;
}
Log.e(TAG, "checkByStep: no reverse cnt = " + cnt);
if (cnt >= 4)
return true;
return false;
}
private boolean checkWin(Point p, boolean isWhite) {
Log.e(TAG, "checkWin: Now is x = " + p.x + " y = " + p.y + " node color = " + (isWhite ? "white" : "black"));
List<Point> array;
if (isWhite) {
array = mWhiteArray;
} else
{
array = mBlackArray;
}
for (Point pt : array) {
Log.i(TAG, "checkWin: " + (isWhite ? "white" : "black") + " array:(" + pt.x +", "+ pt.y + ")");
}
if (checkByStep(p, array, 0, 1)) //上下直线判断
return true;
if (checkByStep(p, array, 1, 0)) //左右直线判断
return true;
if (checkByStep(p, array, 1, 1)) //右朝上直线判断
return true;
if (checkByStep(p, array, -1, 1)) //右朝下直线判断
return true;
Log.i(TAG, "checkWin: false");
return false;
}
4、代码解释:
1)首先,我们通过两个Point的ListArray存储黑白双方已经下了的棋子位置
2)在CheckWin方法中,我们传入了当前的落子位置,同时传入了当前是黑子还是白子
3)通过isWhite参数,我们取出当前黑或者白子的ListArray,然后调用checkByStep函数进行某一个直线方向的判断
4)checkByStep函数,实现了从某一个方向上进行的五连子判断,入参有xdiff和ydiff,表示了该直线的方向。如xdiff=0,ydiff=1,表示了一条垂直的直线方向;xdiff=1,ydiff=0,表示了一条水平的直线方向;xdiff=1,ydiff=1,表示了斜向上的直线方向;xdiff=-1、ydiff=1,表示了斜向下的直线方向
5)在checkByStep函数中,从当前节点,按照xdiff、ydiff,向两个方向进行了遍历,找到两个方向上的相连棋子个数,如果除当前棋子外,直线两个方向还有4个以上的相同棋子,则认为五子连珠,该棋子方获胜
项目源码: