这里以.net为例共享给大家,JAVA一样的,运算符功能都一样
这里主要是共享我花了大半天时间想出来的一个算法。在这之前,首先我们要回忆几个知识点,位运算:
.右移运算符 >> ,|逻辑或,~按位取反,
我们要判断的是 “军” 出棋时,从起点到终点,这两点之前是否有别的棋子存在,如果存在就不能那样走。
首先军可以向四个直线方向走,但是我们要知道从起点到终点往哪个方向走的,我们必须做出判断写if(x1-x2<0&&y1-y2==0) ....if(x1-x2==0&&y1-y2<0) .....等等这样去判断方向,然后再用for循环来遍历这两点之前是否有其他棋子存在,这得写4个if加for循环。下面这段代码只需要一个for循环加if就搞定,看段代码:
private Boolean Che(Enum[,] chess, Point[,] point, Point start, Point end)
{
//得到两点的位置信息
int s_x = (start.X-10)/48;
int s_y = (start.Y-10)/48;
int e_x = (end.X-10)/48;
int e_y = (end.Y-10)/48;
//移动的方向
int x = s_x-e_x;
int y = s_y-e_y;
//是否走的是直线
if (s_x != e_x && s_y != e_y)
{
return false;//不是直线
}
//查看两点之前是否有其他棋子(经典之作呀,花了我半天加一个晚上时间才想出来,从除法想到位移)
for (int i = 1; i < Math.Abs(x) || i < Math.Abs(y); i++)
{
int xx = s_x + (x >> 31 | 1) * i * (((~(-Math.Abs(x))) >> 31) + 1);
int yy = s_y + (y >> 31 | 1) * i * (((~(-Math.Abs(y))) >> 31) + 1);
Enum e = chess[s_x-xx,s_y-yy];//得到经过的坐标点
if (e != null)
{
return false;//中间存在子
}
}
return true;
}
参数说明,chess里记录了棋子,如果没有则为null,point为对应chess的坐标,start为开始移动坐标,end为要移到的目的地位标
(start.X-10)/48;这个算法是得到当前坐标在point二维数组的序号.s_x-e_x这个算法是得到相对于现在的序号是正移的还是负移的
(x >> 31 | 1)这个算法前篇文单有写是取得符号,(负整数就得到-1,正整数或0得到1)
(((~(-Math.Abs(x))) >> 31) + 1)这个算法的功能主要是把除开0以外的所有数变成1,0则不变
下面来说明一下(((~(-Math.Abs(x))) >> 31) + 1)
Math.Abs(x)这个我们可以得到一个非负数,
-Math.Abs(x)加个负号,全转成负数
~(-Math.Abs(x))取反,0取反就得-1,负整数反就得正整数
然后右移31个位,((~(-Math.Abs(x))) >> 31),-1依然是-1,正整数则会变成0
(((~(-Math.Abs(x))) >> 31) + 1)就能实现上面的"把除开0以外的所有数变成1,0则不变"
得到坐标序号s_x + (x >> 31 | 1) * i * (((~(-Math.Abs(x))) >> 31) + 1)
整个思路就是这样。对移位不是很清楚的童鞋可能会有疑问为什么是移31位而不是移32或其他,这个你得去研究一下位移这个东东了.