位棋盘表示法中车和炮的着法生成

这里没有采用Magic Bitboard技术,采用了4个方向扫描最高1位或最低1位的办法,效率虽然比magic bitboard低一点,但代码还是比较容易理解的。

 

 

occupied

attacks = PRESET_RAY_NORTH[fromPos];

blockers = attacks & occupied;

9

8

7

6

5

4

3

2

1

0

000000000

001000000

001100100

000000000

001001000

000000000

000000000

010010110

000000000

001000000

ABCDEFGHI

001000000

001000000

001000000

001000000

001000000

001000000

001000000

000000000

000000000

000000000

ABCDEFGHI

000000000

001000000

001000000

000000000

001000000

000000000

000000000

000000000

000000000

000000000

ABCDEFGHI

 

一个位棋盘,1表示有棋子占据,0表示无棋子。这里的fromPos是C2位置。

C2格子的正北面的格子都可以攻击到

blockingPos = blockers.GetLowestBit( );

此例中表示C5格阻碍了车的前进

 

 

 

PRESET_RAY_NORTH[blockingPos]

attacks ^= PRESET_RAY_NORTH[blockingPos];

 

9

8

7

6

5

4

3

2

1

0

001000000

001000000

001000000

001000000

000000000

000000000

000000000

000000000

000000000

000000000

ABCDEFGHI

000000000

000000000

000000000

000000000

001000000

001000000

001000000

000000000

000000000

000000000

ABCDEFGHI

上面一系列的位运算处理了正北方可以攻击到的位置,同理再处理东面、南面和西面的情况,就可以得到所有可以攻击到的格子的位棋盘

 

C5格正北方的格子

异或后,正好就是位于C2格子的车向北方前进时可以攻击到的所有位置的位棋盘

 

 

复制代码
 1 /*! 车的着法生成 
 2 * \param fromPos 出发位置 
 3 * \param occupied 棋子占据情况的位棋盘 
 4 * \return 可到达位置组成一个位棋盘 
 5 */ 
 6 BitBoard MoveGenerator::RookAttacks( int fromPos, BitBoard occupied ) 
 7 { 
 8     int        blockingPos; 
 9     BitBoard   attacks, partAttacks, blockers; 
10 
11     
12     // 向北扫描
13     attacks = PRESET_RAY_NORTH[fromPos]; 
14     blockers = attacks & occupied; 
15     if ( blockers.H | blockers.L) 
16     { 
17         blockingPos = blockers.GetLowestBit( ); 
18         attacks ^= PRESET_RAY_NORTH[blockingPos]; // mask off beyond blocking square 
19     } 
20 
21  
22     // 向东扫描 
23     partAttacks = PRESET_RAY_EAST[fromPos]; 
24     blockers = partAttacks & occupied; 
25     if ( blockers.H | blockers.L) 
26     { 
27         blockingPos = blockers.GetLowestBit( ); 
28         partAttacks ^= PRESET_RAY_EAST[blockingPos]; 
29     } 
30     attacks |= partAttacks;  
31     
32     // 向南扫描
33     partAttacks = PRESET_RAY_SOUTH[fromPos]; 
34     blockers = partAttacks & occupied; 
35     if ( blockers.H | blockers.L) 
36     { 
37         blockingPos = blockers.GetHighestBit(  ); 
38         partAttacks ^= PRESET_RAY_SOUTH[blockingPos]; 
39     } 
40     attacks |= partAttacks; 
41 
42     // 向西扫描
43     partAttacks = PRESET_RAY_WEST[fromPos]; 
44     blockers = partAttacks & occupied; 
45     if ( blockers.H | blockers.L)  
46     { 
47         blockingPos = blockers.GetHighestBit(  ); 
48         partAttacks ^= PRESET_RAY_WEST[blockingPos]; 
49     } 
50 
51     return attacks | partAttacks; 
52 } 
复制代码

 

 

炮的着法生成可以类似的处理,但要处理吃子的情况。

 

 

occupied

attacks = PRESET_RAY_NORTH[fromPos];

blockers = attacks & occupied;

9

8

7

6

5

4

3

2

1

0

000000000

001000000

001100100

000000000

001001000

000000000

000000000

010010110

000000000

001000000

ABCDEFGHI

001000000

001000000

001000000

001000000

001000000

001000000

001000000

000000000

000000000

000000000

ABCDEFGHI

000000000

001000000

001000000

000000000

000000000

000000000

000000000

000000000

000000000

000000000

ABCDEFGHI

 

一个位棋盘,1表示有棋子占据,0表示无棋子。这里的fromPos是C2位置。

C2格子的正北面的格子都可以走到

blockingPos = blockers.GetLowestBitWithReset( );

此例中表示C5格阻碍了炮的前进,同时要把此位置0

 

 

 

PRESET_RAY_NORTH_SELF[blockingPos]

attacks ^= PRESET_RAY_NORTH

_SELF[blockingPos];

如果有吃子的话
eatPos = blockers.GetLowestBit( );
此例中为C7。

attacks.SetBit(eatPos);
 

9

8

7

6

5

4

3

2

1

0

001000000

001000000

001000000

001000000

001000000

000000000

000000000

000000000

000000000

000000000

ABCDEFGHI

000000000

000000000

000000000

000000000

000000000

001000000

001000000

000000000

000000000

000000000

ABCDEFGHI

000000000

000000000

001000000

000000000

000000000

001000000

001000000

000000000

000000000

000000000

ABCDEFGHI

上面一系列的位运算处理了正北方可以移动到或攻击到的位置,同理再处理东面、南面和西面的情况,就可以得到所有可以生成所有着法。

 

C5正北方的格子,包括C5位置

异或后,正好就是位于C2格子的炮向北方前进时可以移动到的所有位置的位棋盘

   

 

复制代码
 1 attacks = PRESET_RAY_NORTH[fromPos]; 
 2 blockers = attacks & occupied; 
 3 if ( blockers.H | blockers.L) 
 4 { 
 5     blockingPos = blockers.GetLowestBitWithReset(  ); 
 6     attacks ^= PRESET_RAY_NORTH_SELF[blockingPos]; // mask off beyond blocking square 
 7     if ( blockers.H | blockers.L) { 
 8         eatPos = blockers.GetLowestBit(  ); 
 9         attacks.SetBit(eatPos); 
10     } 
11 } 
12 
13 partAttacks = PRESET_RAY_EAST[fromPos]; 
14 blockers = partAttacks & occupied; 
15 if ( blockers.H | blockers.L) 
16 { 
17     blockingPos = blockers.GetLowestBitWithReset(  ); 
18     partAttacks ^= PRESET_RAY_EAST_SELF[blockingPos]; 
19     if ( blockers.H | blockers.L) { 
20         eatPos = blockers.GetLowestBit( ); 
21         partAttacks.SetBit(eatPos); 
22     } 
23 } 
24 attacks |= partAttacks; 
25 
26 partAttacks = PRESET_RAY_SOUTH[fromPos]; 
27 blockers = partAttacks & occupied; 
28 if ( blockers.H | blockers.L) 
29 { 
30     blockingPos = blockers.GetHighestBitWithReset(  ); 
31     partAttacks ^= PRESET_RAY_SOUTH_SELF[blockingPos]; 
32     if ( blockers.H | blockers.L) { 
33         eatPos = blockers.GetHighestBit(  ); 
34         partAttacks.SetBit(eatPos); 
35     } 
36 } 
37 attacks |= partAttacks; 
38 
39 
40 partAttacks = PRESET_RAY_WEST[fromPos]; 
41 blockers = partAttacks & occupied; 
42 if ( blockers.H | blockers.L)  
43 { 
44     blockingPos = blockers.GetHighestBitWithReset(  ); 
45     partAttacks ^= PRESET_RAY_WEST_SELF[blockingPos]; 
46     if ( blockers.H | blockers.L) { 
47         eatPos = blockers.GetHighestBit( ); 
48         partAttacks.SetBit(eatPos); 
49     } 
50 } 
51 
52 return attacks | partAttacks; 
复制代码

 

 

posted @   申龙斌的程序人生  阅读(1325)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
历史上的今天:
2010-09-14 由极点五笔到QQ五笔的转换想到的
点击右上角即可分享
微信分享提示