📄 数据结构——0x88着法产生方法.htm
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0052)http://www.elephantbase.net/computer/struct_0x88.htm -->
<HTML><HEAD><TITLE>数据结构——0x88着法产生方法</TITLE>
<META http-equiv=Content-Type content="text/html; charset=gb_2312-80">
<META content="MSHTML 6.00.3790.536" name=GENERATOR></HEAD>
<BODY background=数据结构——0x88着法产生方法_files/background.gif>
<DL>
<DIV align=center>
<CENTER>
<DT>《对弈程序基本技术》专题 </CENTER></DT></DIV>
<DIV align=center>
<CENTER>
<DT> </CENTER></DT></DIV>
<DIV align=center>
<CENTER>
<DT><FONT face=Arial size=6><STRONG>0x88</STRONG></FONT><FONT face=隶书
size=6>着法产生方法</FONT> </CENTER></DT></DIV>
<DIV align=center>
<CENTER>
<DT> </CENTER></DT></DIV>
<DIV align=center>
<CENTER>
<DT><FONT face="Times New Roman">Bruce Moreland (</FONT><A
href="mailto:brucemo@seanet.com"><FONT
face="Times New Roman">brucemo@seanet.com</FONT></A><FONT
face="Times New Roman">) / </FONT>文 </CENTER></DT></DIV>
<DT>
<DT><FONT face=楷体_GB2312 size=5><STRONG>历史</STRONG></FONT>
<DT>
<DT> 我在<FONT face="Times New Roman">1995</FONT>年香港举行的世界电脑国际象棋锦标赛<FONT
face="Times New Roman">(WCCC)</FONT>上和 <FONT face="Times New Roman">David
Kittinger
</FONT>交流时,他跟我说了这个着法产生的技术,当时我就把它忘了。如今回过头来看,我已经很多次提到这个技术了。由于当时我还不知道它的名称,我就给它起了别的名字。它名称应该是<FONT
face="Times New Roman">0x88</FONT>,即十六进制的<FONT
face="Times New Roman">88</FONT>。
<DT> 之所以称为<FONT face="Times New Roman">0x88</FONT>,是因为<FONT
face="Times New Roman">0x88</FONT>概括了这个技术的要点。
<DT> <FONT face="Times New Roman">0x88</FONT>技术的优势在于:
<DT> <FONT face="Times New Roman">(1) </FONT>它很容易理解;
<DT> <FONT face="Times New Roman">(2) </FONT>代码非常短小,一点也不复杂;
<DT> <FONT face="Times New Roman">(3) </FONT>很容易检查棋子是否超出边界。
<DT>
<DT><FONT face=楷体_GB2312 size=5><STRONG>棋盘表示和基本原理</STRONG></FONT>
<DT>
<DT> 通常的国际象棋棋盘是<FONT face="Times New Roman">8x8</FONT>的格子,格子的“标准”编号应该从<FONT
face="Times New Roman">0</FONT>到<FONT face="Times New Roman">63</FONT>,<FONT
face="Times New Roman">a1</FONT>格是<FONT face="Times New Roman">0</FONT>,<FONT
face="Times New Roman">b1</FONT>格是<FONT face="Times New Roman">1</FONT>,<FONT
face="Times New Roman">a2</FONT>格是<FONT face="Times New Roman">8</FONT>,<FONT
face="Times New Roman">h8</FONT>格是<FONT
face="Times New Roman">63</FONT>,其余的格子由你自己填上。
<DT> <FONT face="Times New Roman">0x88</FONT>采用稍微不同的棋盘,它有<FONT
face="Times New Roman">128</FONT>个格子,<FONT
face="Times New Roman">a1</FONT>到<FONT
face="Times New Roman">h1</FONT>仍旧是<FONT face="Times New Roman">0</FONT>到<FONT
face="Times New Roman">7</FONT>,但是在<FONT
face="Times New Roman">h</FONT>列右边还有从未用到的<FONT
face="Times New Roman">i</FONT>到<FONT
face="Times New Roman">p</FONT>列,简单地说就是把一个虚的棋盘放在实的棋盘的右边。
<DT> 因此<FONT face="Times New Roman">a2</FONT>被编为<FONT
face="Times New Roman">16</FONT>,<FONT face="Times New Roman">a8</FONT>是<FONT
face="Times New Roman">112</FONT>,<FONT face="Times New Roman">h8</FONT>是<FONT
face="Times New Roman">119</FONT>。
<DT> 任意一个格子都符合下面的公式:
<DD>
<DD>指标 = 行号 x 16 + 列号
<DT>
<DT> 你可能会问为什么要这样做,其实有很多理由,这里我们只讨论最关键的。这个理由就是,这样做可以检查射线是否走到了棋盘的左边界或右边界。
<DT> 你可能仍旧不明白。假设你仍然用<FONT face="Times New Roman">8x8</FONT>的棋盘,并且考虑<FONT
face="Times New Roman">a3</FONT>格的车,在<FONT
face="Times New Roman">8x8</FONT>的棋盘上它的编号是<FONT
face="Times New Roman">16</FONT>。现在来产生这个车的目标格子,先从纵线上的着法开始。在纵线上前进一格,就增加<FONT
face="Times New Roman">8</FONT>,<FONT face="Times New Roman">16</FONT>加上<FONT
face="Times New Roman">8</FONT>就得到<FONT
face="Times New Roman">24</FONT>。这个格子是否在棋盘上呢?在<FONT
face="Times New Roman">8x8</FONT>的棋盘上可以检查它是否小于<FONT
face="Times New Roman">64</FONT>。现在<FONT
face="Times New Roman">24</FONT>小于<FONT
face="Times New Roman">64</FONT>,所以它在棋盘上。下一个格子是<FONT
face="Times New Roman">32</FONT>,然后依次是<FONT
face="Times New Roman">40</FONT>、<FONT face="Times New Roman">48</FONT>和<FONT
face="Times New Roman">64</FONT>,<FONT
face="Times New Roman">64</FONT>不小于<FONT
face="Times New Roman">64</FONT>,所以它在棋盘外边,我们就停了下来。
<DT> 非常好,现在我们从<FONT face="Times New Roman">a3</FONT>往下走。<FONT
face="Times New Roman">a3</FONT>是<FONT
face="Times New Roman">16</FONT>,减去<FONT
face="Times New Roman">8</FONT>得到<FONT
face="Times New Roman">8</FONT>,它在棋盘上吗?此时要检查它是否大于或等于零,而<FONT
face="Times New Roman">8</FONT>确实是的。再下一个格子是<FONT face=Symbol>-</FONT><FONT
face="Times New Roman">8</FONT>,因为小于零,所以不在棋盘上。
<DT> 我们不厌其烦做了两次测试,如果只需要做一次测试那就更好了。现在测试棋子是否在棋盘上的代码是:
<DD>
<DD>if ((index < 0) || (index >= 64))
<DT>
<DT> 其实这就包含了两次测试,我们远远没有满足,因为它完全可以只做一次测试:
<DD>
<DD>if (!(index & 0x40))
<DT>
<DT> 这就涵盖了判断棋子超出棋盘下边界和超出棋盘上边界的两种情况。超出棋盘上边界时,由于大于<FONT
face="Times New Roman">64</FONT>而<FONT
face="Times New Roman">0x40</FONT>置为<FONT
face="Times New Roman">1</FONT>,超出棋盘下边界时,用补码表示负数的机制使得<FONT
face="Times New Roman">0x40</FONT>也置为<FONT face="Times New Roman">1</FONT>。
<DT> 如果你还没有明白,那么你最好停下来别看下去了,否则下面要说的东西对你来说就是天书。
<DT> 如果你留意一下,你会注意到我们只让车朝上朝下走,而没有让它朝左朝右走。我们之所以不让它朝左朝右走,是因为这套机制不允许这么做,它无法判断朝左或朝右的射线是否到达棋盘的边界。如果你从<FONT
face="Times New Roman">a3</FONT>开始朝右走,每走一格加<FONT
face="Times New Roman">1</FONT>直到<FONT
face="Times New Roman">h3</FONT>,此时你可以继续加<FONT
face="Times New Roman">1</FONT>到达<FONT face="Times New Roman">a4</FONT>。<FONT
face="Times New Roman">a4</FONT>仍就在棋盘上,然而没有什么技巧可以让你判断是否超越了<FONT
face="Times New Roman">h</FONT>列。朝左走也一样,从<FONT
face="Times New Roman">a3</FONT>格开始减<FONT
face="Times New Roman">1</FONT>,就会到<FONT
face="Times New Roman">h2</FONT>,它仍然在棋盘上,但是国际象棋里没有哪个棋子能这么走。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -