我正在使用位板代表棋盘并检查合法动作。我坚持的事情是计算滑动件攻击中源和目标方块之间的占用率。 我不想通过查找来做,所以我想弄清楚是否有可能在之间找到正方形的掩码而没有查找。例如,在下面的板中,c4上有一个Rook:
8 0 0 0 0 0 0 0 0
7 0 0 0 0 0 0 0 0
6 0 0 0 0 0 0 0 0
5 0 0 0 0 0 0 0 0
4 0 0 R 0 0 0 0 0
3 0 0 0 0 0 0 0 0
2 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0
a b c d e f g h
给定一个代表空方块(或占用方块,更容易)的位板和伪有效移动Rf4(白嘴鸦可以从c4移动到f4),如何获得方块d4-e4的掩码(不包括源和目的地广场)?
我认为,一旦明确,垂直移动将很容易,并且可以使用旋转位板计算对角线移动。
编辑:位板用ulong / unsigned int64表示,每包8位代表实际电路板的等级/行。
答案 0 :(得分:3)
我将在这里做一些假设:电路板存储为64位数字,每个8字节块代表一行。行中的每个位代表一列(a..h)。您有起始和终止位置作为从零开始的坐标。即: start = "C4" = [2,3]; end = "F4" = [5,3]
对于列数增加的水平移动,您可以计算移动的距离: d = (F4-C4 = 3)
。减去1以排除目的地,然后d-1位的“踪迹”t是 t = (1<<(d-1))-1
。移动与源片相邻的轨迹以获得蒙版M: M = t<<(start.row*8 + start.column+1)
。
这相当于
M = ((1<<d)-2)<<(start.row*8 + start.column)
另一种方式是水平移动:
d = (C4-F4 = -3)
t = (1<<(-d-1))-1
M = (t<<dest.column+1)
//-or-
M = ((1<<-d)-2)<<(dest.row*8 + dest.column)
垂直增加动作:
d = (C7-C4 = 3)
t=(1<<8)
(d-1) times: { t |= (t<<8)}
M = t << (start.row*8 + start.column)
垂直减少移动:
d = (C4-C7 = 3)
t=(1<<8)
(d-1) times: { t |= (t<<8)}
M = t << (dest.row*8 + start.column)
对于垂直移动,您可以通过存储最大“垂直轨迹”VT = 0x0101010101010101 = 72340172838076673
来替换d上的循环。然后为实际移动掩盖正确的位数。
这会减少对M = (VT & ((1<<(d*8)) - 2)) << (row*8+column)
的影响。
你可能会为对角线移动做类似的事情。从最大对角线路径DT = 0x0102040810204080
开始,应用掩码将其减少到d
设置位,并切换到开始或结束位置,具体取决于哪个更接近边缘。这需要仔细测试,以确保没有边缘情况缠绕到错误的行。
已修改为排除源和目标,并修复一次性错误
答案 1 :(得分:1)
如果没有做一些前期计算并为片段移动生成所有可能的掩码(一定的可能性),我希望在运行时构建掩码很可能在时间上和简单的一样昂贵。查找每个方块的方法。
答案 2 :(得分:0)
获取方向(dx,dy)/ dx
的统一向量在这种情况下,(1,0)
然后重复增加该矢量的当前位置,直到到达目的地。正在进行增量/分配相应的矩阵单元格。