📄 解剖大象的眼睛——中国象棋程序设计探索(十):实用程序片段.htm
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0055)http://www.elephantbase.net/computer/eleeye_utility.htm -->
<HTML><HEAD><TITLE>解剖大象的眼睛——中国象棋程序设计探索(十):实用程序片段</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=解剖大象的眼睛——中国象棋程序设计探索(十):实用程序片段_files/background.gif>
<DL>
<DIV align=center>
<CENTER>
<DT><FONT face=隶书 size=6>解剖大象的眼睛</FONT><FONT
size=6><STRONG>——</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">*</FONT> <FONT
face="Times New Roman">2005</FONT>年<FONT
face="Times New Roman">11</FONT>月初稿,<FONT
face="Times New Roman">2006</FONT>年<FONT face="Times New Roman">1</FONT>月修订
</CENTER></DT></DIV>
<DIV align=center>
<CENTER>
<DT><FONT face="Times New Roman">( * </FONT>联系地址:复旦大学化学系表面化学实验室,<FONT
face="Times New Roman">eMail</FONT>:<A
href="mailto:webmaster@elephantbase.net"><FONT
face="Times New Roman">webmaster@elephantbase.net</FONT></A><FONT
face="Times New Roman">)</FONT> </CENTER></DT></DIV>
<DT>
<DT><FONT face=Arial size=5><STRONG>(</STRONG></FONT><FONT face=楷体_GB2312
size=5><STRONG>十</STRONG></FONT><FONT face=Arial size=5><STRONG>)
</STRONG></FONT><FONT face=楷体_GB2312 size=5><STRONG>实用程序片段</STRONG></FONT>
<DT>
<DT> <FONT face="Times New Roman">ElephantEye</FONT>的源程序包里有个<FONT
face="Times New Roman"><utility></FONT>目录,其中包含了很多实用程序片段,不仅仅是针对象棋程序的。由于程序片段中没有中文注释,所以这里作一下简要的介绍。
<DT>
<DT><FONT face=Arial size=4><STRONG>10.1 Visual Basic</STRONG></FONT><FONT
face=楷体_GB2312 size=4><STRONG>下的原子语句</STRONG></FONT><FONT face=Arial
size=4><STRONG>(atom.cpp/atom.bas)</STRONG></FONT>
<DT>
<DT> <FONT face="Times New Roman">ElephantEye</FONT>的部分代码可编译成<FONT
face="Times New Roman">CCHESS.DLL</FONT>,成为界面程序<FONT
face="Times New Roman">ElephantBoard</FONT>的一部分。然而由于<FONT
face="Times New Roman">Visual Basic</FONT>处理数据结构的能力很弱,调用<FONT
face="Times New Roman">CCHESS.DLL</FONT>时需要调用一些低级语句<FONT
face="Times New Roman">(</FONT>例如<FONT
face="Times New Roman">QuickBasic</FONT>的<FONT
face="Times New Roman">VARPTR</FONT>、<FONT
face="Times New Roman">MKI</FONT>、<FONT
face="Times New Roman">CVI</FONT>等在<FONT face="Times New Roman">Visual
Basic</FONT>中已经淘汰的语句<FONT face="Times New Roman">)</FONT>,为此<FONT
face="Times New Roman">ElephantEye</FONT>提供了这些原子,以保证数据结构使用的便利。
<DT> 在<FONT face="Times New Roman">Visual Basic</FONT>调用<FONT
face="Times New Roman">API</FONT>函数的参数传递过程中,注意事项有:
<DT> <FONT face="Times New Roman">(1) </FONT>指针型变量用<FONT
face="Times New Roman">ByRef</FONT>声明,自定义结构只能用<FONT
face="Times New Roman">ByRef(</FONT>引用方式<FONT
face="Times New Roman">)</FONT>传递参数;
<DT> <FONT face="Times New Roman">(2) </FONT>如果自定义结构用<FONT
face="Times New Roman">ByVal(</FONT>传值方式<FONT
face="Times New Roman">)</FONT>传递参数,则必须把它们转化为<FONT
face="Times New Roman">Visual Basic</FONT>的内部类型;
<DT> <FONT face="Times New Roman">(3) Visual Basic</FONT>的字符串类型<FONT
face="Times New Roman">(Windows</FONT>内部类型是<FONT
face="Times New Roman">BSTR)</FONT>必须用<FONT
face="Times New Roman">ByVal</FONT>传递参数,<FONT face="Times New Roman">Visual
Basic</FONT>会自动将其转化为<FONT face="Times New Roman">LPCSTR</FONT>类型;
<DT> <FONT face="Times New Roman">(4) API</FONT>函数返回<FONT
face="Times New Roman">LPCSTR</FONT>类型时,在<FONT face="Times New Roman">Visual
Basic</FONT>下必须假定为<FONT face="Times New Roman">Long</FONT>类型。
<DT> 我们最感兴趣的是最后一条,<FONT face="Times New Roman">LPCSTR</FONT>类型的字符串由<FONT
face="Times New Roman"><atom.bas></FONT>中的<FONT
face="Times New Roman">MkBStr</FONT>函数转换为<FONT face="Times New Roman">Visual
Basic</FONT>的字符串类型<FONT face="Times New Roman">(BSTR)</FONT>。例如在<FONT
face="Times New Roman">Visual Basic</FONT>下调用开局编号分析器<FONT
face="Times New Roman">ECCO.DLL</FONT>,调用方式如下:
<DD>
<DD>Declare Function EccoIndex Lib "ECCO.DLL" Alias "_EccoIndex@4" (ByVal
FileMoveStr As String) As Long ' ECCO.DLL中的EccoIndex函数在Visual Basic下的接口
<DD>Declare Function EccoOpening Lib "ECCO.DLL" Alias "_EccoOpening@4" (ByVal
EccoIndex As Long) As Long ' ECCO.DLL中的EccoOpening函数在Visual Basic下的接口
<DD>EccoStr = MkL(EccoIndex("C2.5N8+7")) ' 获得ECCO编号的字符串,这里将返回"B05"
<DD>OpeningStr = MkBStr(CvL(EccoStr)) ' 获得上述编号对应的开局名称,这里将返回"中炮对进左马"
<DT>
<DT><FONT face=Arial size=4><STRONG>10.2 </STRONG></FONT><FONT face=楷体_GB2312
size=4><STRONG>汇编语言</STRONG></FONT><FONT face=Arial
size=4><STRONG>(x86asm.h)</STRONG></FONT>
<DT>
<DT> 汇编语言是为了弥补<FONT face="Times New Roman">C</FONT>语言的不足,<FONT
face="Times New Roman"><x86asm.h></FONT>主要提供以下两方面的功能:
<DT> <FONT face="Times New Roman">(1) </FONT>操控互斥<FONT
face="Times New Roman">(Mutex)</FONT>变量的原子语句,有<FONT
face="Times New Roman">Increment</FONT>、<FONT
face="Times New Roman">Decrement</FONT>、<FONT
face="Times New Roman">Exchange</FONT>等,用于多线程的调度;
<DT> <FONT face="Times New Roman">(2) 32</FONT>位和<FONT
face="Times New Roman">64</FONT>位整数的乘除法和位移,有<FONT
face="Times New Roman">LongMulDiv</FONT>、<FONT
face="Times New Roman">LongMulMod</FONT>等,解决了“<FONT
face="Times New Roman">Int64 = Int32 x Int32</FONT>”等计算问题。
<DT> 尽管<FONT face="Times New Roman">Windows</FONT>和<FONT
face="Times New Roman">Unix</FONT>也有相应的库函数来支持这些功能,但是汇编语言通常以内联的形式调用,所以速度上会有优势。
<DT>
<DT><FONT face=Arial size=4><STRONG>10.3 </STRONG></FONT><FONT face=楷体_GB2312
size=4><STRONG>空转</STRONG></FONT><FONT face=Arial
size=4><STRONG>(idle.h)</STRONG></FONT>
<DT>
<DT> 在程序空闲期间,应该把<FONT
face="Times New Roman">CPU</FONT>资源交还给系统,这时就要调用空转函数<FONT
face="Times New Roman">Idle()</FONT>,也可以直接调用<FONT
face="Times New Roman">Windows</FONT>或<FONT
face="Times New Roman">Unix</FONT>下都的休眠函数<FONT
face="Times New Roman">(Sleep()</FONT>或<FONT
face="Times New Roman">usleep())</FONT>。
<DT>
<DT><FONT face=Arial size=4><STRONG>10.4 </STRONG></FONT><FONT face=楷体_GB2312
size=4><STRONG>随机数</STRONG></FONT><FONT face=Arial
size=4><STRONG>(longrand.h)</STRONG></FONT>
<DT>
<DT> <FONT face="Times New Roman">ElephantEye</FONT>在使用随机数时,没有用<FONT
face="Times New Roman"><stdlib.h></FONT>中的<FONT
face="Times New Roman">rand()</FONT>函数,是出于以下几点考虑的:
<DT> <FONT face="Times New Roman">(1) rand()</FONT>函数的有效位数只有<FONT
face="Times New Roman">15</FONT>位<FONT
face="Times New Roman">(</FONT>最大数为<FONT
face="Times New Roman">0x7fff)</FONT>,这远不能满足程序的需要,用多个<FONT
face="Times New Roman">rand()</FONT>函数来拼凑只是权益之计;
<DT> <FONT face="Times New Roman">(2) rand()</FONT>函数的可靠性无法得到保障,因为我们不知道它的算法;
<DT> <FONT face="Times New Roman">(3) </FONT>如果以<FONT
face="Times New Roman">Zobrist</FONT>键值的形式来描述开局库中的局面,那么每次给定相同的种子以后,产生的<FONT
face="Times New Roman">Zobrist</FONT>键值都必须相同。但各种<FONT
face="Times New Roman">C</FONT>语言的编译器中给出的<FONT
face="Times New Roman">rand()</FONT>函数,我们无法确定其工作原理是否相同,因此也就不知道它们是否会产生相同的<FONT
face="Times New Roman">Zobrist</FONT>键值了。
<DT> <FONT face="Times New Roman">ElephantEye</FONT>的随机函数包含在<FONT
face="Times New Roman"><longrand.h></FONT>中,它采用了“乘同余法”,公式是这样的:
<DD><FONT face="Times New Roman"><EM>I</EM><SUB><EM>j</EM>+1</SUB> =
(<EM>a</EM> x <EM>I</EM><SUB><EM>j</EM></SUB>) mod <EM>m</EM></FONT>
<DT> 该公式可以用<FONT face="Times New Roman"><x86asm.h></FONT>中的<FONT
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -