如何进入深度搜索呢(如何探测数独已无法使用唯一法呢)?
·建立一个记分板,叫做depth,类型为dummy 上面这个CB链有两个功能,一是探测是否有81个含有yes标签的AEC,二是检测数独盘的上一次状态是否和这一次一样(没有填任何一个数,也就是无法使用唯一法了),如果一成立,则将find的round改为3,并重置所有分数,告诉玩家:数独解决完毕;如果二成立,则关闭执行唯一法流程的RCB,开启深度搜索流程。下面这个CB链是将find的round改为2(执行深度搜索流程),然后把所有含有not标签的AEC的depth分数改为-2333(定为一个小于-80或者大于81的数即可),后面我们会用到。
如前面一样,首先要给find进行tp(红色部分)。蓝色部分是探测find是否归位(也就是数独是否解决完毕)。白色部分是如果还没到最后,则继续解。这里蓝色部分用了一个条件制约的CCB,当find归位之后就不会执行继续解下去的模块了。
·创建一个记分板,叫做sort,类型为dummy。 ·召唤一个叫做sort的盔甲架,用于给单元格内待探测的数独排序和探测是否为无解单元格,sort的sort默认为1分。 看到第一层的CB链,以一个排序接一个加分,看代码: /execute @e[type=ArmorStand,name=find] ~ ~~ execute @e[type=AreaEffectCloud,name=1,r=0,tag=!kill] ~ ~ ~ execute@e[type=AreaEffectCloud,name=1,r=0,tag=!x,c=1] ~ ~ ~ scoreboard players operation@e[type=AreaEffectCloud,name=1,r=0,tag=not,c=1] sort =@e[type=ArmorStand,name=sort] sort tag为kill是被剪枝掉的数,x是本次分支内,这个数的分支已确认无解的数(注意,c=1的意思是选择它自己,而且前面制约了条件tag=!kill,后面就也会包含这个制约,所以无需担心(这里十分感谢Potter_Lee的帮助))。这就是剪枝后的东西,具体剪枝后面会讲。每当排一次序,sort的sort就要+1,以达到排序的目的,排序完后,sort的sort就要恢复为1分。 有的人可能会问,为什么只要执行sort为1分的呢,因为每次探测都会重新排序,就会一直有sort=1的AEC,除非它是无解单元格。 第二层的CB链是判断单元格是否无解,首先一个是给sort为1分的AEC加上叫做try的tag,表示这个数将要被尝试。如果存在sort为1分的AEC,那么条件制约的CCB就会执行剪枝搜索,如果不存在sort为1的AEC,那么,就会进行回退处理,回到上一层。现在先来讲讲剪枝是如何执行的吧。
其实和之前那个行列宫删数是差不多的,只不过这里不是杀死AEC,而是加上一个kill的tag,如果你杀死这个AEC,到时候到退回来就不好办了,对吧,那么先看一个示例代码: execute @e[type=ArmorStand,name=find] ~ ~ ~execute @e[type=AreaEffectCloud,tag=try,r=0,name=1] ~ ~ ~ detect ~ ~-2 ~minecraft:stained_glass 1 execute @e[type=AreaEffectCloud,tag=!kill,name=1] ~ ~~ detect ~ ~-2 ~ minecraft:stained_glass 1 scoreboard players tag@e[type=AreaEffectCloud,r=0,c=1,tag=!try] add kill 因为考虑到后面要根据层数移除本层的kill标签,所以这里排除了给带有kill标签的AEC加kill标签(好像是多余的。。。)。这里就要多加几个CCB了,当round=3的时候,就要执行tp(给那个CB改auto为1b),而且还要给刚刚加上kill标签的AEC赋值目前层数。还有一个CCB是给sort的层数(depth)+1。那,如何探测刚刚加上kill标签的AEC呢?在之前我们将所有空格处的AEC(含有not标签的AEC)的depth改为了-2333,那么就只要用选择器检测depth分数为-2333而且tag=kill的AEC,将其depth进行赋值即可。 下面是对无解单元格的处理。
首先执行上面这一层的CB链,如果这个单元格是含有yes标签的AEC,就直接跳过就行了,如果真的是无解单元格,那么才执行下面这一层的CB链。 如何处理呢? 在倒退之前先要移除本层所有的状态,将其还原到刚开始执行深度搜索法的时候的状态。那么需要移除哪些状态呢?kill标签、x标签、try标签、深度(好像就这些了)。 如何探测是否为上一层呢?还记得吗,只有sort执行成功才能将深度+1,那么find到了无解单元格,深度是不会变的,那么久将所有含有try标签的AEC的深度-=sort的深度,如果为0,则将find传送过去,记得在将它们的层数加回来。先别急者把深度-1,还有一些状态没移除。很简单,只要探测层数相同,就移除kill标签、x标签。然后因为盔甲架已经tp回上一层了,那么给盔甲架所在单元格内的AEC的try改为x,那么sort会根据这一点往后执行一个数,接着再给sort的深度-1。执行完这个以后,改auto就只能改排序的那个了(总不能刚tp回来又tp过去吧),然后再次执行流程,如此循环往复。
继刚才那个探测find是否归位接着讲,这里是将所有AEC的tag改为yes并remove掉not,下面这个是执行填数的CB链。然后调用探测是否为81个数都填完的模块,解数独就这样结束了。 |