中国象棋 军 规则判断

来源:互联网 发布:外貌协会 知乎 编辑:程序博客网 时间:2024/05/17 00:00

 

这里以.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或其他,这个你得去研究一下位移这个东东了.

原创粉丝点击