效果详情大家来玩中国象棋棋

热门搜索:
热门专题:
给我讲解一下中国象棋棋子步法的描述规则
提问者:| 浏览次数:4517次 |问题来自:全国
就是如“车二平五”、“马一退二”“炮三平六”之类的描述
输入内容已经达到长度限制
您还可以输入
验证码错误
回答 共1条
已被 <span id="Reward 人打赏
TA回答得不错,我决定赏
注:每次只能打赏1积分哦~
1、中国象棋只有横坐标,没有纵坐标。因为古人习惯从右往左阅读。所以横坐标红方是从右往左数一到九,黑方也是从右往左数1到9。2、如果一个棋子是平行移动,那么就只读横坐标,比如红车从最右边移到最左边,无论这个车在哪一行都叫车一平九,如果红方两个车都在最右边,只是所处的行数不同,那么用前后区分,可以叫前车平九,或者后车平九。3、如果一个棋子只有纵向移动,比如车和炮等,因为没有纵坐标,所以是数出来的。比如红方一开始最右边的车往前走了一步,就叫做车一进一。同样无论这个车在哪一行,比如是巡河车,只要它在最右边(一路线),往前走了一步,都叫做车一进一,往后退三步,就叫车一退三。4、特殊之处是马、士、相等子的移动,因为它们是斜着运动,所以不存在数数移动了几步的问题,而是要参考横坐标。比如一开始进一步右马,往中间进是马二进三,往边路跳是马二进一,并不是进了三步和一步的意思,而是看马要跳的点的横坐标。5、初学者看棋谱摆子容易弄错的地方是这样的。直行他知道是数格子,进几就往前数几,退几就往后数几。但是往往横行,也会忘记看横坐标,比如第一步右炮平中路当头炮,是炮二平五,有人会数格子,认为是炮二平三,那就不对了。
登录并提交回答
登录回答可获积分奖励
还没有账号?
如果您发现不正当的内容或行为,请及时联系我们!
举报内容:
举报原因:
(可多选)
含有反动的内容
含有人身攻击的内容
含有广告性质的内容
涉及违法犯罪的内容
含有违背伦理道德的内容
含色情、暴力、恐怖的内容
含有恶意无聊灌水的内容
Copyright &
Soufun Holdings Limited, All Rights Reserved
北京搜房科技发展有限公司 版权所有
文明办网文明上网 举报电话:010- 举报邮箱:象棋软件引擎分析,详细信息,引擎是怎么搜索招式的???_百度知道
象棋软件引擎分析,详细信息,引擎是怎么搜索招式的???
提问者采纳
作者:nicepeople10中象棋软搜索引擎揭密(一) fenon北京大赛终于过去了, 在这场盛事前后这段时间, 静下心来回顾了走过的象棋研究的路子,心得感触良多.为了纪念这段时间的美好, 我决定把这段时间积累的对象棋引擎的心得, 总结分享出来我个人希望通过这篇文章,把一些顶尖棋软的知识普及开来,提高开源象棋软件的水平.1. 搜索引擎和审局之间的关系, 如何建立阅读下面的内容时, 首先需要了解几个背景知识a. 人工智能的博弈搜索树和PVS搜索之间的关系b. PVS搜索是无损搜索c. PVS的搜索效率和搜索次序的关系首先明确几点:a. 做一个全PVS的搜索, 在限定了层数的情况下, 如果基于不正确的知识(比如子力表),并不能保证一定能把杀棋找出来(可能会跑去吃子)b. 为了提高棋力, 无损搜索PVS是不足够的, 还是需要剪枝的c. 搜索树和审局之间的关系, 首先知识必须能够引导搜索到正确盘面(这个地球人应该都知道), 第二是避免搜索把正确的分支剪除掉(这个谈论得少一些,我以前曾经有很长一段时间不知道)我认为, 审局和搜索之间的关系的建立, 在于a. 知识是带有正确的倾向性的(只能说是倾向性,因为知识很难做到全面准确)b. 搜索是根据知识而采取剪枝方式的(这个下面详细分析)下面我举一个简单的例子, 来说明知识和搜索之间的关系帅_____| | |马 _| 将_|_兵| _ |_ |_ |_象在这个盘面, 兵只要靠近王一步, 就可以将死了对方, 但是基于子力表做depth=1的PVS搜索,只会选择: 兵吃象, 有利, 而且评估子力分数很高, 所以吃象那么, 有什么办法避免这种情况呢?a. depth=1的时候不做剪枝b. 给予引擎审局的知识, 告诉引擎保持&马非底线兵&这种组合对将才具有杀伤力这样就给出了两种选择, 哪种更好?实际上, b这种选择有两种局限a. 局限于现在对审局模型建立的水平, b这种情况需要花费大量的人力功夫来维护完整的知识, 而且很难做到准确b. 目前的引擎的搜索棋步排序, 大都是基于最近访问-&杀棋步-&吃子步这样的棋步排序方法, 我们可以很容易想象到, 使用全面复杂的知识, 会引起搜索结果冲突(凑着一个吃子或者杀棋的步子去走, 但是最后发现达不到预期的效果), 大大降低了搜索的效率正是因为上面的原因, 现在我所了解到的高端引擎, 大都是通过控制剪枝的危险程度, 来弥补知识的不足, 比如, 在nullmove中限制depth&=2, 或者, 在lmr(late move reduction)--如变种:fruit的history pruning, 控制depth&=3, 都是利用控制剪枝来弥补知识的缺陷.我们很清楚知道, depth&=2的时候, 都限制了不能剪枝的话, 那么刚才的盘面, 并不需要任何知识,就可以找出杀棋步, 但是, 这个是不是我们需要的呢? 我想不是的, 如果限制了depth&=2不能剪枝的话, 我们会发现我们的搜索, 产生了大量的节点, 啊, 天啊, 可怕的搜索浪费当然, 最理想的方法是, 搜索排序的次序是基于知识的, 而且盘面评估是基于知识的, 如果我们能够达到这样的效果, 嗯, 我想depth&=1不剪枝的限制也可以去掉了, 这样的引擎肯定效率更高吧现在, 让我们想想, 哪些分支我们是不想被错误剪掉的? 当然是杀棋步, 杀棋&吃子, 基于子力表的搜索PVS, 很可能漏掉的棋步是杀棋步, 而这个恰恰是我们不想见到的对于攻杀激烈的中国象棋,可以说两个引擎的差别在于,谁能更快更准确找到杀棋步.口语化一点来说,给你多搜索两层的能耐,你能保证绝对能通过蚕食我的大子把我变成光棍司令? 尤其是随着高层效应的出现(引擎和硬件的发展,搜索的层数越来越大), 这种可能更是趋向于零, 所以, 我们应该尽量避免漏掉杀棋步我知道有很多引擎的做法是, 对有潜在攻势的局面做出模糊判断, 并且赋予高分, 如越容易发生杀棋的棋步, 给予越高的分数, 例如三子归边的分数&马炮的分数, 这样就可避免因为吃马炮而漏掉杀棋, 但是这种模糊判断有些致命的缺点a. 模糊知识,会造成大量的搜索浪费(条件越不准确, 越容易造成搜索浪费)b. 模糊知识会造成错误的判断, 导致乱弃子c. 引擎发展需要更长的发展周期, 需要大量的对局来积累知识一种比较适中的解决方案是, 采取depth&=1不剪枝的搜索方法, 并且给予depth=1时候, 可以形成杀棋的棋型知识的判断这种方法的原理是, depth=1的搜索,可以达到depth==2的效果, 并且可以避免模糊知识判断带来的误搜索的缺陷这种解决方案的优点在于a. depth=1可以生成杀棋的知识可以穷举b. 知识准确度高,可以大幅度减少搜索浪费缺点在于, depth=1可以形成的杀型, 覆盖面有限, 剩下的知识, 还是需要通过一些模糊判断来补充, 当然, 这种补充少很多了, 而且完善起来也难度降低很多上面的介绍可以说是知识模型的缺陷造成的对搜索的依赖, 下面我再来说说, 知识对搜索产生的影响我们假设有一个盘面, depth=11的PVS全搜索才能发现杀棋, 那么下面的知识, 做depth=10搜索时,哪种才能走出正确的棋步呢?a. 对depth=1情况可杀棋的知识评估b. 对depth&=2情况可杀棋的知识评估c. 子力组合(如单车单王胜单王)和子力优势d. 位置分(不是子力表,只是位置的分数,如灵活度等)实际上我们很容易就可以判断出来, depth=1的知识评估,能走出正确的棋步,情况b也可能走出正确的棋步, 但是会有一定的误判, c, d大都情况下, 走不出正确的棋步我们现在对所有的知识打分, 这个分数依赖的因素应该是(depth, 准确度, 搜索浪费), 即score=形势*(准确度/(depth*搜索浪费))因为用评估盘面希望得到的分数等于depth&3的棋步, 准确度是相当低甚至会引起大量错误的, 所以我们对盘面评估会有一定的限度,同理,评估depth=1变化内的盘面,我们可以做到非常精确,这个时候可以给一个准确的分数上面提到的a,b,c,d四种知识,对中国象棋软件的知识覆盖面是相当广了, 我们可以很简单看出, a可以奖励&马炮的分数, 而b因为可能走入误区, 常常只是奖励&士相的分数, 子力组合不会产生误区,但是需要搜索很深才能得出正解,所以分数也是不会太高,位置分则更小了但是, 给予引擎全面而准确的知识是否恰当呢? 即, 知识是不是越全面, 棋力越强呢? 很多朋友都问过这个问题, 并且认为恰当的知识会减少搜索量, 而且这也是很多朋友追求的方向. 我实践的答案是否. 搜索其实是追求一种性价比, 单位搜索量内, 能得到最好的搜索结果, 才是好的搜索. 简单说说原理, 当盘面有两三个知识倾向都可以产生PV路径的时候, 只会带来引擎的左右徘徊, 尤其在杀棋的盘面, 会大大降低搜索的效率, 这部分的实践结果, 我会在&6. 建立以kingsafety为核心的审局, 以及审局模型的详细分析&再进一步详细分析这里我想纠正一个错误的想法,常常有一些不了解搜索引擎原理的朋友,拿一些盘面,让棋软去判断,看谁能更快更准找到正解,要尽快解出这种盘面,往往需要大量的模糊知识,或者足够的深度,前者无疑是把棋软送上绝路的一种做法.这种评估只是有一定的意义,但绝对不是衡量棋软水平的标准.2. fruit引擎分析, fruit引擎能达到2600的高度的原因 (对比crafty进行阐述)fruit引擎并不追求速度,实际上,fruit并没有使用流行的bitfile,bitrank技术或者bitboard,所以fruit的nps在国际象棋引擎中并不算高(我想比起crafty应该比不上),如果说两者的差异在于评估的话,嗯,那不在我所了解的范围,我只谈谈两者引擎上面的差别a. fruit的pv节点的意义以及基于pv节点搜索剪枝的效率能够在搜索中, 把PV节点区分出来, 并且根据节点类型进行剪枝, fruit可以说对PVS理解是非常深刻的.PV节点的定义大家可以查查相关资料, 既然PV节点表示正确的搜索结果, 那么就肯定不应该剪掉. 同样,对于不是PV节点的, 就不会找出正确的搜索路径, 这就应该剪掉.这个也是fruit剪枝的理论依据。道理是这样说, 但是我们一开始并不知道每一个节点的类型, 所以在搜索的时候, 会假设某个节点不是PV节点, 然后看它是否会fail, 如果fail,再做PV节点的搜索.假如这种假设是成立的, 那么就成功完成了对该非PV节点路径的剪枝,否则,需要重新搜索,因为对PV节点假设判断的搜索是做windows=1的搜索,所以耗费的代价是很低的.下面来看看fruit的实现方法,我认为fruit对PV节点理解的实现方法非常优雅.int search_root(){本节点做PV搜索if (树根节点并且首节点)下一层节点为PV节点 // 这个时候还没有找出PV路径,所以必须做PV节点搜索else{下一层节点做假设不是PV节点的搜索if (fail)下一层节点做PV节点的搜索}}int search_full(){根据上一层对该节点的判断, 进行节点搜索if (首节点 || 假设不是PV节点的搜索) // 当假设不是PV节点时, windows=1这个时候不应该假设,应该直接计算了,否则就是重复计算浪费时间下一节点的节点类型跟本节点类型一致else{下一层节点做假设不是PV节点的搜索if (fail)下一层节点做PV节点的搜索}}中象棋软搜索引擎揭密(二) fenoncrafty中,对PV节点的区分方法,是PV节点是否落在[-vMate,+vMate]中,实际上,这种判断方法,对子树的PV节点并不能做出有效的判断,这也直接导致了搜索效率的下降正是因为PV节点的特殊意义,所以凡是PV节点,fruit都不做剪枝,不从HASH取步,甚至PV节点还需要加强搜索的强度(参考TogaII)b. fruit的nullmove剖析我们先来看看fruit的nullmove的实现if (UseNull && depth &= NullDepth && node_type != NodePV) { // 不对PV节点进行剪枝, 而且depth==1时不剪枝(原因参考上文)if (!in_check // 不是将军盘面&& !value_is_mate(beta) // 当落入一个不知道上限的窗口时,不剪枝,这种情况发生在height==2时&& do_null(board) // 国象规矩限定子&=2&& (!UseNullEval || depth &= NullReduction+1 || eval(board) &= beta)) { // 根据距离叶子或者alpha,beta搜索中,棋形的评估进行控制我想, 对上面的控制条件,大家都是很好理解的, fruit中NullRedcution==3, 这个可以理解为fruit审局做得比较完善,depth&=4进入审局搜索盘面评估的结果, 逼近搜索的结果, 而eval则是对depth&4时候剪枝的控制条件,这种控制条件往往是根据棋形进行控制, crafty是控制大子的个数, fruit是控制评估的结果, 考虑到这个结果因引擎而异, 我就不在这里讨论哪种条件才是更好的了new_depth = depth - NullReduction - 1;move_do_null(board,undo);value = -full_search(board,-beta,-beta+1,new_depth,height+1,new_pv,NODE_OPP(node_type));move_undo_null(board,undo);fruit的nullmove会导致一种和以外不同的搜索情况产生,crafty的做法是,上一层做了NULLMOVE,现在轮到我了,我应该移动棋步,但是fruit的做法,会引起双方的等待,这是否正确?答案是,很正确.首先,考虑算法上面的等价性,连续做NULLMOVE,其实等价于我不知道你是否做了NULLMOVE,不过我也尝试做一个NULLMOVE,看你是否能对我造成威胁,这个并不违背NULLMOVE的思想,而且一个不会产生PV路径的节点,做搜索有意义吗?没有意义.既然如此,那么就剪掉吧.对nullmove的结果,fruit有两种特别的处理手段第一,不保存结果,因为fruit的算法的剪枝,会让实际的值和nullmove产生的值差别很大第二,对某些特殊情况,fruit会做一个nullmove verify的search, fruit尝试全面利用nullmove, 但是某些情况, nullmove成功的概率有限, 需要做一定的验证fruit对nullmove的实现方法,可以说得上是历史性的(开源的引擎来说),这个算法的优异,是fruit搜索效率特高的一个根本原因c. fruit的qs加强在上文中, 我已经提过, fruit是尝试通过控制depth&=1使用全搜索的方法, 尽可能发现杀棋, 那么, 对nullmove来说, 如果depth&=4,发生了一个剪枝, 立刻进入了qs, 马上就把杀棋步剪掉了为了防止这种情况, fruit对刚进入qs的棋步,不单单生成吃子步,还生成将军步,这可以有效防止把杀棋步漏掉的情况.qs里面,fruit对吃子步产生的将军步,会解将,让对方保持继续进攻的机会,这也是为了防止qs漏掉杀棋步的一种有效措施虽然qs的论述很少,而且很简单,但是,对qs中,将军的检查,却有着消耗20%性能,提高50%功能的性价比,这个也是crafty所缺少的d. fruit的history pruning要了解history pruning, 首先建议参考国象中成熟的算法lmr (late move reduction)的论述fruit对lmr引入了history value,并且对搜索结果做了verify,有效避免了lmr曾经的fail high的问题这里就不对history pruning的限制条件做详细的阐述了,实际上这种防止危险的检查方法和nullmove的限制是类似的,而且会根据不同引擎知识和搜索结合的特点而存在差异history pruning经实践证明, 是一种非常有效的剪枝方法, 并且绝对不会对棋力有降低的影响(其实根本原因是不会漏掉杀棋步)history pruning根据国外的测试,能够提高elo 100,旧版的crafty并没有history pruninge. fruit的hash实现方法fruit的hash实现方法,经实践,大概比crafty的方法提高了5%~10%的性能fruit对每个盘面,保存了一个上界和一个下界,如果对一个盘面搜索时,发现该盘面的搜索范围上界比过往的下界都要小, 则返回保存的下界, 如果发现搜索范围的下界比保存的上界要大, 则返回保存的上界, 如果发现盘面落入保存的窗口中, 则当保存的上界和下界重合而且搜索深度比当前搜索深度更深时, 返回保存的结果这种hash的处理方法,修正了crafty中,只能对单边情况保存的不足, 有效提高了效率需要注意的地方是, 在iterative search中, 每次fruit都会把搜索出来的PV路径都保存到hash中,这是用于取步(不是取值), 还有,在处理hash冲突时候, fruit使用了多个cluster的方法...需要细究的细节很多, 大家有兴趣可以仔细看看fruit的实现f. fruit的search root move listfruit对每次搜索后对root节点记录分值,并根据分值重新排序,以便下一次使用,当棋步产生振荡的时候(在两个棋步之间徘徊)会有效提高引擎的搜索效率g. fruit的FAIL SOFT嗯, 关于FAIL SOFT以及实践的方法, 可以参考纵马奔流的****和fruit的代码, 我就不再无聊多说一次了..3. fruit 2.1和TogaII1.2.1的差异,elo 100的差距原因首先需要说明的是,我是用diff的方法,比较两者在搜索实现上的差别的, 应该是没有遗漏的两者的差别列举如下a. 延伸的差异, 根据特定棋形做了depth+1的搜索, 也就是越搜反而越深(当然TogaII有手段防止过深)b. 剪枝的差异, 包括打开futility, delta, 并且对底层也做了history pruningc. 对棋步稳定的盘面(只产生一个PV路径), 用渴望窗口搜索, 减少搜索量d. 对危险情况的搜索的加强两者差异原理分析简单概括TogaII的改进,那就是利用国际象棋的知识调整了fruit的搜索树,对危险的盘面进行了更深的搜索,否则就剪掉.首先,TogaII最有效的改进,是在叶子附近,利用history value把证明曾经无效的叶子节点丢弃掉,这是一个非常有效的算法,这里面的道理值得我们深思?为什么我们不能够发现一个这样的算法呢?如果光是观察futility和delta剪枝法, 我想肯定会有人对我提出疑问? 不是说这些根据子力情况剪掉的分支会漏掉杀棋步吗? 为什么还打开剪枝, OK, 我来一个简单的回答, 假如已经是用了知识判断过这类分支并不危险, 那就可以剪掉了.TogaII能改进fruit的原因基于对国际象棋的深刻理解(也许是大量的测试的证明), 它的剪枝和延伸, 是相辅相成的, 如果有人想尝试这个方向, 千万不要只开剪枝或者只加延伸这个方向, 是在搜索树中, 加入对棋类知识的判断. 调整搜索树更适合某种棋规.4. fruit算法应用于中象引擎的分析及中象引擎算法改进分析下面的内容,是基于上述阐述的一些具体应用的例子,可对引擎做出一定的修正a. nullmove改进nullmove限制条件中, 当depth&=4时, 进入nullmove. 这种情况会忽略了depth=1可能产生的杀棋步, 当审局的知识缺乏该方面的内容时, 会漏掉杀棋步这个时候, 可以根据自己引擎的审局知识的特点, 做depth=1的search_verify代码如下if (depth&=4)do_if (nullscore&=beta)do_search_verify(depth=1);这种方法可以避免一些杀棋情况的漏算, 这个也可以算是搜索和知识结合的一个典型例子吧b. history pruning改进考虑下面的情况[炮]吃车1, 车2吃[炮], 车2移动, 和车1移动, 这两个棋步, 会引起同样的history value的减少, 虽然限制了history pruning发生在不吃子的情况, 但是, 中象的交换频率远&国象, 这种情况对fruit中historyvalue&9830就剪枝(60%)显然不适合, 因为中象发生上面的情况要高多了, 而historyvalue&9834(60%)只要该棋步有一次被检索的情况就会发生, 这个时候, 修正historyvalue&16384*45%, 可以有效减少误判c. futility剪枝及delta剪枝的意义分析嗯, 这个, 首先参考TogaII和fruit对比的文章futility和delta, 如果不会漏掉杀棋步, 或者, 在不会被对方杀死的情况, 非常有助于扩大自己的子力优势, 这是这两个剪枝法的机制决定的(注意,这两个剪枝法的依据是扩大子力优势,所以适用的范围是有限的,对双方对杀的盘面是会削弱攻击能力的)我建议使用这两个剪枝法, 当然是建立在调整过搜索树以后(避免在容易引发杀棋的盘面使用,常见的手段是判断kingsafety,是否处于被攻击状态中)中象棋软搜索引擎揭密(三) fenond. 棋步排序的改进从PVS搜索的原理出发, 搜索效率取决于搜索次序常见的棋步排序是历史步-&吃子步-&killer-&etc, 这是基于最大化子力优势的搜索, 当对杀时, 这种搜索排序效率是非常低的.考虑killer棋步,如果能够发生一个killer步的分数是杀棋步,那么调整棋步排序为历史步-&killer-&吃子步-&etc,这样就很好地把杀棋和吃子都结合起来了5. fruit算法和象眼的差异, 如何提高象眼的棋力通过本篇的介绍, 希望能够把开源的象眼程序, 改进到一个全新的高度, 假如有人希望一起完成象眼的改进, 请站内和我联系下面是我认为可以有效提高象眼棋力的几个地方a. 基于PV节点的nullmove pruningb. qs加强c. History pruning及TogaII剪枝法d. 棋步排序e. hash的改进f. IID算法修正g.search root move list6. 建立以kingsafety为核心的审局, 以及审局模型的详细介绍a. 对盘面区分阶段, 不同阶段采取的策略是不同的, 开中残差异是很大的实际上, 开局通过开局库和子力位置分+若干简单知识, 是很容易走出正确的棋步盘面的, 这个研究不深, 我更多是依赖开局库解决这个问题残局时候, 调整位置分表, 判断子力组合, 这个时候因为子力很少, 基本上难以进取, 更多是应该考虑防守, 控制搜索的危险程度和给予适当的分数, 很容易做到这点中局是比较复杂的, 下面详细说说我所理解的地方b. 对某个阶段的知识, 不要给引擎太多的选择, 避免引擎找出多个PV路径, 引起棋步的来回选择, 如中局, 应该集中思考杀棋或者扩大子力的优势c. 上面1.讲述了搜索和知识之间的关系, 其中也提及了depth=1时候的杀棋知识评估的重要性, 但是, 只是局限于depth=1的杀棋知识, 我们的盘面判断力还是很有限的, 这个时候怎么办? 我们能不能对depth&=2的情况进行评估我提供一个实践的方法, 那就是分层次打分.比如: 三子归边的判断, 我们通过以下三种层次评分(a) 有沉底炮, +分 (depth=3)(b) 有沉底炮和车可做炮架, +分 (depth=2)(c) 有沉底炮和车并且马进入了可以助攻的区域, +分 (depth=1)刚才在上面的审局和搜索的关系中,我列举了4种知识,并且强调了知识只应该选择有效的,下面分别说说哪些知识是必须的,不在下面列表内的知识,我都不做判断了a. 准确的杀型利用位置分值提示车马兵攻击王周围,依赖搜索完成b. 模糊的杀型(a) 当头炮 (空头炮,镇中)(b) 底炮 (三子归边)(c) 双车杀c. 子力组合,只做会引起问题的子力组合判断,如兑子后双马不佳d. 某些特别容易出问题的知识的补充7. 国际象棋Rybka的胜利以及将来棋软发展的一些展望一些未来的研究方向, 所以个人的意见应该是一些胡言乱语,仅作笑料上面所说的一切, 都是基于知识会有一个确定的分数, 但是, 这明显是错误的, 谁能说三子归边是400分,而不是395分呢? 有没有一种方法, 可以动态评估这个分数, 从而达到知识的最优化呢?第二,传说中的根据知识排序棋步的方法在国外流行的认为Rybka超越其他软件的原因是因为更聪明的搜索和知识, 从作者言论和Rybka反映的信息做一个猜测(nps超低, 搜索准确度超高), 一致认为Rybka在搜索和评估中, 都采取了全新的方法其中一个流派3moves现在被认为是Rybka最有可能采取的方法(包含了我的理解补充)什么是3moves? 首先, 当前盘面移动一步, 对可以攻击的子,计算3步内可以攻击的点集,这个点集每个点都有权重.那么,多个攻击子做交集的时候, 密度最高权重最高的区域, 就是当前盘面最容易攻击的位置, 这表明了这一个棋步的攻击能力当这个棋步能攻击到王或者其他子时, 这自然就是一个好的棋步,这时候根据点集的情况进行算分,自然是非常准确的.这种方法超越了子力表和知识分数的局限, 而且更好理解了棋规, 也难怪被认为是最有可能的以上转载,不知是否你想要的?
提问者评价
哦,谢谢,不知道象棋软件不运用棋谱,那他是怎么实现走棋的???
其他类似问题
为您推荐:
您可能关注的推广
象棋的相关知识
其他1条回答
跑龙套的吗,一边去
我又不会下象棋
那你就是跑龙套的呀,还不一边去
我就喜欢跑龙套
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁博雅中国象棋首创单人PK多人模式
该开发者其它应用
简介:酒逢知己千杯少,棋遇对手古难求。博雅中国象棋首创单人PK多人模式,可以同时与多个对手博弈。
特色玩法:
游戏大厅:强大防作弊系统,3种房间(自由场、10分钟场、20分钟场),专业象棋竞技规则!
好友对战:所有的好友均可成为你的对手,一个人可同时与多人进行对战,成就大师的殿堂。
单机游戏:两种等级设置,强大AI系统,谁说机器不如人,不信,试一试!
     
北京微梦创科网络技术有限公司&&
中文(简体)
中文(繁体)
Copyright &#include&stdio.h&
#define BYTE unsigned char
int main(void) { BYTE i = 81; while(i--) { if((i / 9) % 3 == (i % 9) % 3) continue; printf("A = %d, B = %d\n", i /9 + 1, i%9 + 1); } return 0; }
&将&和&帅&各在自己的3*3的格子间里面走动,我们共需要验证9*9=81种位置关系,这也是i=81的由来。此外我们要明白 i/9和i%9的含义。我们知道,整数i可以由部两分组成,即var=(var/9)*9+var%9 ,其中var&n。我们注意到,在i从81到0变化的过程中,var%9的变化相当于内层循环,var/9的变话相对于外层循环。这样,作者就巧妙地用一个变量i同时获得了两个变量的数值。
可以把变量i想象成一个两位九进制的变量,而i在计算机中存储的值是i的十进制表示。则i/9的计算机处理结果,即结果直接去掉小数点后部分的结果即是此九进制数的第二位,而i%9即是此九进制数的个位。本程序用此九进制数的第二位保存A的位置,个位表示B的位置。最大值为88,即为十进制的80.程序从十进制的80,即九进制的88遍历到十进制的0,即九进制的0。将符合条件的位置全部输出。
问题扩展:如何利用一个变量达到三重循环的效果。也就是说,如果给定下面的循环:
&int counter = 0;
&for( int i = 0; i & 5; i++ ) &
for( int j = 0; j & 4; j++ ) &&
for( int k = 0; k & 3; k++ ) &&
System.out.println("counter="+counter+"\t, i="+i+", j="+j+", k="+k); &&&
counter++; &&&
其结果如下: &
counter=0 , i=0, j=0, k=0 &
counter=1 , i=0, j=0, k=1 &
counter=2 , i=0, j=0, k=2 &
counter=3 , i=0, j=1, k=0 &
counter=4 , i=0, j=1, k=1 &&&
....中间略 &
counter=59& , i=4, j=3, k=2
(1)我们如何用一个打印出相同的结果?
(2)如果是N重循环呢? &&
面对第一个问题,实际上就是对原始的中国象棋将帅问题进行了一个扩展,即在棋盘上添加一个&王&,其行走规则和将帅 一样。于是棋盘变成了三国争霸:-) ,将帅王可以走动的格子数分别为3、4、5,它们之间的互斥条件可以按需要设定。 && &&&&
这时,就需要只用一个变量遍历一个三重循环。直观的方法是像方法一那样把一个4字节的INT拆开来用。
我这里只关注方法二。 && &&&&
只用一个变量解决扩展的中国象棋将帅问题,我们的代码应该是如下的样子: &&
int var = 3*4*5; &&
while( var-- ) &&
if( /** 冲突条件 **/ )//发生冲突 &&&&&
&   &&&&
else&&& &&&&&&&&
printf(/** 打印可行的位置 **/); && }
在冲突条件中,我们需要知道var取得某个特定的值(即第var+1次循环)的时候的i,j,k分别是多少(这样我们才能判定将帅位置是否冲突) &&&&
从上例的结果中我们可以看到,counter的值(即当前的循环次数)和三元组(i,j,k)是一一对应的,越是外层的循环变化越慢,他们满足什么关系呢? &&&&
&k的取值最好确定,我们都知道是var%3。 &&&&
在原始的将帅问题中我们知道,j的值应该是 var/3,但是由于j上面还有一层循环,就需要做些调整,变成var/3%4 &&&&
最外层循环i的值则为(var/(3*4))%5. &&&&&&&&& 即:
k=var%3&&&&& //其下没有循环了 &&&&&&&&&&&&
&j=var/3&& //其下有几个循环长度为3的循环 &&&&&&&&&&&
&i=var/(3*4). //其下有几个循环长度为3*4的循环 &&&&&
于是4重循环的公式我们也可以轻松得出: &
for( int i = 0; i & 5; i++ ) &&&&
  for( int j = 0; j & 4; j++ ) &&&&&&
&    for( int k = 0; k & 3; k++ ) &&&&&&&&
&      for( int p = 0; p & 3; p++ ) &&& &&
&p=var%2 //其下没有循环了 &&
k=var/2&&&&& //其下有几个循环长度为2的循环 &&
j=var/(2*3)) //其下有几个循环长度为2*3的循环 &&
i=var/(2*3*4)//其下有几个循环长度2*3*4的循环 && &&
下面就是一个变量实现三重循环
int var = 2*3*4*5;
while( var-- & 0)
System.out.println("var="+var+" , i="+((var/(2*3*4))%5)+
                              ", j ="+((var/(2*3))%4)+",&&
&                              k="+((var/2)%3)+", &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&                              p="+var%2);
结果是: &&
var=119 , i=4, j=3, k=2, p=1 &&
var=118 , i=4, j=3, k=2, p=0 &&
var=117 , i=4, j=3, k=1, p=1 &&
...中间略 &&
var=5 , i=0, j=0, k=2, p=1 &&
var=4 , i=0, j=0, k=2, p=0 &&
var=3 , i=0, j=0, k=1, p=1 &&
var=2 , i=0, j=0, k=1, p=0 &&
var=1 , i=0, j=0, k=0, p=1 &&
var=0 , i=0, j=0, k=0, p=0&& && &&
&N重循环原理也是一样,就不再赘述了。
阅读(...) 评论()

我要回帖

更多关于 大家来玩中国象棋 的文章

 

随机推荐