第一范文网 - 专业文章范例文档资料分享平台

Java版中国象棋项目设计论文

来源:用户分享 时间:2025/5/21 1:49:29 本文由loading 分享 下载这篇文档手机版
说明:文章内容仅供预览,部分内容可能不全,需要完整文档或者需要复制内容,请下载word后使用。下载word有问题请添加微信号:xxxxxxx或QQ:xxxxxx 处理(尽可能给您提供完整文档),感谢您的支持与谅解。

3.3.2 Zobrist键值的用途

Zobrist键值通常用在散列键值当中,而散列键值在象棋程序里有以下几个作用: 1、用Zobrist键值来实现置换表。置换表是一个巨大的散列表,来保存以前搜索过的局面,这样可以节省很多搜索的时间。如果需要对某个局面搜索9层,可以从置换表中查找该局面,如果它已经搜索过9层,那么不必去重复搜索。置换表的另一个并不起眼的作用是,它可以帮助我们改善着法的顺序。

2、可以用Zobrist键值制造一个很小的散列表,来检测当前着法路线中有没有重复局面,以便发现长将或其他导致和局的着法。

3、可以用Zobrist键值创建支持置换的开局库。 3.4 Java中实现Zobrist键值

本系统使用一个key和一个lock结合来区分每个局面,这样发生冲突(即两个局面对应的key和lock一样)的概率几乎为0。示例代码及相关说明如下

1、填充数组。

上述的三维数组现在改变为二维(将颜色与棋子兵种类型合并) ??

public static long ZobristKeyPlayer;//改变走子方的key public static long ZobristLockPlayer;//改变走子方的lock public static long[][] ZobristKeyTable = new long[14][90]; public static long[][] ZobristLockTable = new long[14][90]; ?? static{ ??

zobristGen();

}

public static void zobristGen() { int i, j;

Random rand = new Random();

long RandSeed;

RandSeed = 1;

rand.setSeed(RandSeed);

ZobristKeyPlayer = rand.nextLong(); for (i = 0; i < 14; i ++) {

//0:红帅1:红仕2:红相3:红马4:红车5:红炮6:红兵 //7:黑将8:黑士9:黑象10:黑马11:黑车12:黑炮13:黑卒 for (j = 0; j < 90; j ++) {

ZobristKeyTable[i][j] = rand.nextLong(); } }

ZobristLockPlayer = rand.nextLong(); for (i = 0; i < 14; i ++) { for (j = 0; j < 90; j ++) {

ZobristLockTable[i][j] = rand.nextLong();

- 17 -

} } }

2、移子函数

当移动(添加、删除)一个棋子时,将当前局面的Zobrist键值与键值表中该棋子的键值进行异或操作,同时也与改变走子方的键值进行异或操作。 public class ChessPosition{ long ZobristKey, ZobristLock;

//当前局面的zobrist键值 public ChessPosition{ ??

ZobristKey=0;//初始化为0 ZobristLock=0; ?? } ??

public void makeMove(int Square, int Piece, boolean IsAdd) { ?? ZobristKey^=ZobristKeyTable[PieceType][Square];

ZobristLock^=ZobristLockTable[PieceType][Square]; ZobristKey ^= ZobristKeyPlayer;//改变走子方 ZobristLock ^= ZobristLockPlayer; ?? } }

3、开局库:开局库的实现,将在“搜索方法”中说明。

- 18 -

第四章 着法生成

着法生成在不同的象棋引擎中差异较大。本章使用位棋盘生成着法的基本原理。高级的国际象棋引擎通常具备一次只生成一小部分着法的能力。例如,仅生成象走的着法,马走的着法,“将”的着法,所有的吃子着法等等,这正是位棋盘的强项。那为什么用这种方式生成着法呢?原因是生成着法耗费一定的时间。如果引擎在检查了一部分着法后发现了必须走的棋,那它就无需生成余下的棋步了。因此,可能先生成所有吃子的着法,如果没有满意的棋再生成余下的着法。(用来减少耗时的着法生成策略很多——发挥你的想象力吧)。

大名鼎鼎的免费国际象棋引擎Crafty(其作者是Robert Hyatt博士)使用三个着法生成函数。一个用来生成所有伪合法吃子着法,一个生成所有伪合法不吃子着法,最后一个生成所有摆脱被将军状态的着法。注意前两个函数生成的是伪合法的着法。就是说,这些函数生成的着法并非都是合法的。例如,你要生成所有将军的着法并且发现了一步你想走的棋,但随后发现这步不合法再把它抛弃。这看起来很奇怪,但它确实比那种在所有局面下都严格生成合法着法的策略更快!Hyatt博士曾经这样解释:当国王被将时,你需要生成摆脱被将的着法,这时大部分生成的着法是不合法的,在这种局面中你使用生成所有合法着法的策略会帮你节省时间;但在大多数局面中,生成的着法都是合法的,推迟验证合法性会更有效率。

中国象棋的着法生成与此类似,先生成所有伪合法的着法,存入静态数组中。在对局中可以用“查表”的方式查找生成的伪着法,并对其合法性作出判断。这样可以节省大量的时间。 4.1伪合法着法的生成

伪合法着法包含几类: ? 各兵种的不吃子着法 ? 各兵种的吃子着法 ? “将”和摆脱“将”的着法

其中,马、相(象)、兵、帅(将)、仕(士)的吃子着法与其对应的不吃子着法规则相同。(伪合法着法并不考虑被吃的棋子的颜色——该棋子是对方的棋子还是己方的棋子,也不考虑该子是否能动,例如动了该子,双方的帅将会面。)炮和车的不吃子着法规则相同,但分为纵向横向行走两类。炮的吃子着法分为纵向和横向两类,车的吃子着法也分为纵向和横向两类。马和象的着法要考虑蹩马腿和塞象眼。将军的着法单独作为一类。

本程序使用静态数组存储生成的位合法着法,先对其作一些说明。

- 19 -

4.1.1 数组及其下标的含义

1、保存帅(将)、仕(士)、相(相)、马、兵的伪合法静态数组如下:

public static final int[][] KingMoves=new int[90][8]; public static final int[][] AdvisorMoves=new int[90][8]; public static final int[][] BishopMoves=new int[90][8]; public static final int[][] ElephantEyes=new int[90][4]; public static final int[][] KnightMoves=new int[90][12]; public static final int[][] HorseLegs=new int[90][8];

public static final int[][][] PawnMoves=new int[90][2][4];

第一个下标说明棋子所在的格,第二个下标含义不尽相同。帅(将)在某个位置最多有4种走法,例如KingMoves[13][0]=12表示帅在13格(e1格)时可以走到12格(当然,也可以走到14、4、22格,保存到其他几个数组元素中)。第5种(如果前面只有3种着法,则此处是第4种)保存的是非法着法即KingMoves[13][4]=-1,其作用作为查询算法的“哨兵”,提高查询算法的速度。为了速度(以位移运算取代除法运算),第2个坐标值用2的整次方幂。(在后面所讲的开局库和置换表的大小设置是2的整次方幂也是这个道理。)兵的走棋规则需要分颜色,红色的垂直走棋方向和黑色的垂直走棋方向是相反的。兵最多有三种走棋方法。AdvisorMoves[90][8]保存的是士的着法。BishopMoves[90][8]保存的是相(象)的着法,ElephanEyes[90][4]保存的是相(象)着法对应的塞象眼的位置。KnightMoves和HorseLegs是马的着法和蹩马腿的位置。

2、车、炮的伪合法着法静态数组如下:

- 20 -

public static final int[][][] FileNonCapMoves=new int[10][1024][12]; //共十条横线,FileNonCapMoves[y][bitWordY][index]=newY,进 public static final int[][][] FileRookCapMoves=new int[10][1024][4]; public static final int[][][] FileCannonCapMoves=new int[10][1024][4]; public static final int[][][] RankNonCapMoves=new int[9][512][12]; //RankNonCapMoves[x][bitWordX][index]=newX,平

public static final int[][][] RankRookCapMoves=new int[9][512][4]; public static final int[][][] RankCannonCapMoves=new int[9][512][4]; public static final int[][] FileNonCapMax=new int[10][1024]; //FileNonCapMax[y][bitwordY]=MaxY//进退

public static final int[][] FileNonCapMin=new int[10][1024]; //FileNonCapMax[y][bitwordY]=MinY

public static final int[][] FileRookCapMax=new int[10][1024]; public static final int[][] FileRookCapMin=new int[10][1024]; public static final int[][] FileCannonCapMax=new int[10][1024]; public static final int[][] FileCannonCapMin=new int[10][1024]; public static final int[][] RankNonCapMax=new int[9][512];//平

搜索更多关于: Java版中国象棋项目设计论文 的文档
Java版中国象棋项目设计论文.doc 将本文的Word文档下载到电脑,方便复制、编辑、收藏和打印
本文链接:https://www.diyifanwen.net/c7qbr70tyqv0a0pl1tyxy_5.html(转载请注明文章来源)
热门推荐
Copyright © 2012-2023 第一范文网 版权所有 免责声明 | 联系我们
声明 :本网站尊重并保护知识产权,根据《信息网络传播权保护条例》,如果我们转载的作品侵犯了您的权利,请在一个月内通知我们,我们会及时删除。
客服QQ:xxxxxx 邮箱:xxxxxx@qq.com
渝ICP备2023013149号
Top