Minecraft(我的世界)中文论坛

标题: 【CBL|pca】【1.9命令方块】"无延迟"else、else if 及嵌套(不需scb)

作者: pca006132    时间: 2015-11-6 23:29
标题: 【CBL|pca】【1.9命令方块】"无延迟"else、else if 及嵌套(不需scb)
本帖最后由 pca006132 于 2015-11-6 23:34 编辑

大家好,我是pca。今天来和大家说说1.9的chain CB(下称CCB)如何做到else/else if及嵌套
首先让我来介绍一下if、else、if else嵌套的概念(如果早就知道的话就可以跳过~)


if、else、else if

什么是if呢?相信大家都知道,if就是如果
比如说,如果地图上有盔甲架,就say 地图上有盔甲架
常见的表达方法:



至于else呢,就是当前面的if的条件没有达成,就执行下面的东西(否则就不执行)。也就是否则
比如说,如果地图上有盔甲架,就say 地图上有盔甲架;否则就say 地图上没有盔甲架



else if则是else 和 if一起使用,如果前面的if的条件没有达成,就执行另外一个if
例子: 如果有玩家叫a,就say 这里有个玩家叫a;否则如果有玩家叫b,就say这里有个玩家叫b;否则如果有玩家叫c,就say这里有个玩家叫b;否则就say这里没有任何叫a/b/c的玩家


从这个例子上可以看到,if、else、else if是可以配搭一起用的



嵌套

比如说,我们要在地图上有盔甲架并且有叫a的玩家的时候就say地图上有盔甲架和a玩家我们可以怎么办呢?我们可以用and,然而这需要scb,然而这并不符合本文的中心,而且也会很麻烦(如果要有盔甲架但是不能有叫a的玩家呢?或者是有盔甲架并且有叫b的玩家呢?难道写多几次?)
所以我们需要一个叫嵌套的东西
嵌套就是在if 里弄多一个if之类的东西,以下是一个例子
if (地图上有盔甲架)
{
    if (地图上有叫a的玩家)
    {
        say .......
    }
}
里面的东西和一般的基本上是一样的。无论是if、else、还是else if也能够嵌套别的if



1.9 CCB的特性

在了解如何做到if那些控制之前,你需要明白CCB的一些特性,不然的话是不能够明白那个系统的原理的。

首先,CCB是会把之前指着它的CB的信号延续下去无论它有没有被激活/conditional的条件是否满足
只要对着它的ICB(普通CB),RCB(自带高频的CB)有被激活(有没有成功执行命令是完全没关系的),或者对着它的CCB有信号传过来,它就会传递信号

第二,CCB在激活了(有红石信号激活/auto)并且满足条件(见下)的情况下就会执行命令

第三,CCB在以下情况下被称之为"条件满足"
(比如??(第一个箭头为前一个命令方块及其方向,后一个箭头为conditional模式的CCB及其方向),如果前一个成功执行,后面那个就会为满足条件)
(比如
??(第一个箭头为前一个命令方块及其方向,后一个箭头为conditional模式的CCB及其方向),即使前一个成功执行,后面那个还是不满足条件,因为不是对着其箭头尾部)

接下来会使用的特殊简写(除了第一个CB是普通CB之外,所有都是CCB)
cond:命令
该CCB是在conditional模式的
mark:名字
以指定名字的盔甲架来标记下一个命令方块的位置


CCB的if、else、else if
首先,这个我经常使用blockdata来更改CCB的auto,因为auto为0的时候,它不会执行命令,但是会传递信号。而且,blockdata几乎是没有延迟的(执行后会马上看到结果),起码没有1gt的延迟,在CCB这种每个命令执行时间少于1gt的情况下(微观延迟)是极度有用的。

——if——
if就相当简单,后面的命令加上cond就可以了。
比如
testfor @e[type=ArmorStand]
cond:say there are armorstands
cond:say 第二个命令
如此类推,用我上面的表达方法就是
if (有盔甲架)
{
say there are armorstands
say 第二个命令
}
因为如果第一个条件不符合,后面的第一个CB就不能够执行,第二个也因为第一个不能执行而无法执行,如此类推,一串的cond命令方块就无法执行了
——————————————

——else——
else呢,就稍微难一点了,我们需要用到blockdata
比如
  1. testfor @e[type=Item]
  2. cond:say 这里有物品
  3. cond:execute @e[type=ArmorStand,name=1] ~ ~ ~ blockdata ~ ~ ~ {auto:0b}
  4. mark:1
  5. say 这里没有物品
  6. execute @e[type=ArmorStand,name=1] ~ ~ ~ blockdata ~ ~ ~ {auto:1b}
复制代码
整个事情就好像是,当检测到有物品,就说有物品,并且令名字为1的盔甲架所在的命令方块无法执行命令,只能传递信息。最后把所有命令方块重置(令其能够执行命令)
如果没有物品,名字为1的盔甲架所在的命令方块就不会被blockdata,因此能够执行命令。

————————————

——else if——
else if其实和else差不多,都是利用那个auto的原理,然而这个稍微比较复杂点。例子:
  1. testfor @e[type=Item]
  2. cond:say 这里有物品
  3. cond:execute @e[type=ArmorStand,name=1] ~ ~ ~ blockdata ~ ~ ~ {auto:0b}


  4. mark:1
  5. testfor @e[type=Creeper]
复制代码
其实,就是在else里增加一个if那样子而已。

相信大家也看到那个say 2、say 1和say end了。到底我弄那些看起来什么也表达不了的东西来干啥呢?
其实就是想告诉大家,有cond:和没有cond:是很大差别的。有cond:,就是当前面的成功执行才可以执行这个命令,所以就是在{}里面
如果没有cond:,就是在{}外面



嵌套!
warning!警告!
前方可能会让人头疼,如果不熟习上方的概念的话切勿看下方。(:D其实看看也无妨,然而我不确保解释的好)

好了,说了那么多,嵌套怎么做呢?
其实很简单的,大家看到我写的那个mark:1吗?1是什么意思呢?其实我就是把它当做为第一层那么看的。
嵌套的话,就是不同名字的盔甲架,1、2、3、4.....
第一层的在一开始的是auto:1b的,其他则是auto:0b(这里是简化了的)
如果符合某条件,它就把所有和它同一层次的CB变成auto:0b,并且把所有的下一层次CB变为auto:1b。
到了另外一个部分(比如if {} else {}就是两个部分),就把它需要用到的层次重置(以减少需要重置的次数)

相信大家也看到不明所以了,以下是一个例子,希望能够让大家更容易明白这个概念。
  1. execute @e[type=ArmorStand,name=1] ~ ~ ~ blockdata ~ ~ ~ {auto:1b}
  2. execute @e[type=ArmorStand,name=2] ~ ~ ~ blockdata ~ ~ ~ {auto:0b}
  3. execute @e[type=ArmorStand,name=3] ~ ~ ~ blockdata ~ ~ ~ {auto:0b}

  4. testfor @e[type=Arrow]
  5. cond:execute @e[type=ArmorStand,name=1] ~ ~ ~ blockdata ~ ~ ~ {auto:0b}
  6. cond:execute @e[type=ArmorStand,name=2] ~ ~ ~ blockdata ~ ~ ~ {auto:1b}

  7.     mark:2
  8.     cond:testfor @e[type=Item]
  9.     cond:execute @e[type=ArmorStand,name=3] ~ ~ ~ blockdata ~ ~ ~ {auto:1b}
  10.     cond:execute @e[type=ArmorStand,name=2] ~ ~ ~ blockdata ~ ~ ~ {auto:0b}

  11.         mark:3
  12.         cond:testfor @a
  13.         cond:say there are arrows,items and players
  14.         cond:execute @e[type=ArmorStand,name=3] ~ ~ ~ blockdata ~ ~ ~ {auto:0b}

  15.         mark:3
  16.         say there are arrows and items

  17.     mark:2
  18.     testfor @a
  19.     cond:say there're arrows and players
  20.     cond:execute @e[type=ArmorStand,name=2] ~ ~ ~ blockdata ~ ~ ~ {auto:0b}

  21.     mark:2
  22.     say there are arrows


  23. execute @e[type=ArmorStand,name=2] ~ ~ ~ blockdata ~ ~ ~ {auto:0b}
  24. mark:1
  25. testfor @e[type=Item]
  26. cond:execute @e[type=ArmorStand,name=1] ~ ~ ~ blockdata ~ ~ ~ {auto:0b}
  27. cond:execute @e[type=ArmorStand,name=2] ~ ~ ~ blockdata ~ ~ ~ {auto:1b}

  28.     mark:2
  29.     cond:testfor @a
  30.     cond:say there are items and players
  31.     cond:execute @e[type=ArmorStand,name=2] ~ ~ ~ blockdata ~ ~ ~ {auto:0b}

  32.     mark:2
  33.     say there are items

  34. mark:1
  35. testfor @a
  36. cond:say there are players
复制代码
首先就是把所有的第一层次CB变为auto:1b,并且把所有其他层次的CB变为auto:0b
然后如果检测到箭,就把第二层次的变为auto:1b(进入第二层次),并把第一层次的变为auto:0b(把后面的命令忽略掉)
    如果检测到物品,就把第三层次变为auto:1b(进入第三层次),并把第二层次的变为auto:0b(把之后的忽略掉)
        如果检测到玩家,就say检测到箭、物品和玩家。然后把第三层次的变为auto:0b(忽略掉后方的)
        否则,就say 检测到箭和物品。
    否则,如果检测到玩家,就say 检测到箭和玩家。并且把第二层次的变为auto:0b
    否则,就say 检测到箭。
把所有第二层次的CB重置为auto:0b(不用重置第三层次是因为这里用不到第三层次)
否则,如果检测到物品,就把第二层次的变为auto:1b(进入第二层次),并把第一层次的变为auto:0b(把后面的命令忽略掉)
    如果检测到玩家,就say 检测到物品和玩家。并且把第二层次的变为auto:0b
    否则,就say 检测到物品
否则,如果检测到玩家
就say检测到玩家。



很简单吧= ̄ω ̄=,就是不停的把不同层次disable/enable。

深夜码字哦,各位客官来捧个场吧QAQ
{:10_521:}

[groupid=546]Command Block Logic[/groupid]
作者: andylizi    时间: 2015-11-6 23:31
看了半天啥也没看懂……这个东西有实际意义么,似乎以前1.8 1.7时代也蛮好的……
作者: pca006132    时间: 2015-11-6 23:35
andylizi 发表于 2015-11-6 23:31
看了半天啥也没看懂……这个东西有实际意义么,似乎以前1.8 1.7时代也蛮好的…… ...

然而你就看了顶多3分钟吧。。。
这东西确实有意义的,解决了只能if不能else 的问题
作者: ufof    时间: 2015-11-6 23:40
话说CB能不能够面向对象
作者: 林扬骐    时间: 2015-11-6 23:45
lz,if可以用多个命令方块朝向一个chain做到,else可以用多个“需要前面的命令方块成功输出”做到,还有,那个“需要前面的命令方块成功输出”的一组必须是一条直线
作者: pca006132    时间: 2015-11-6 23:46
ufof 发表于 2015-11-6 23:40
话说CB能不能够面向对象

这个嘛,我不懂编程,然而我觉得应该就是吧。
毕竟记分板的分数、nbt等等绝大多数的都是针对实体/方块来搞的。
当然,能够做到的东西当然比编程少很多,毕竟我们能用的就是Mojang给我们的那些东西,而且经常有"特性",局限实在是太大了。
作者: pca006132    时间: 2015-11-6 23:52
林扬骐 发表于 2015-11-6 23:45
lz,if可以用多个命令方块朝向一个chain做到,else可以用多个“需要前面的命令方块成功输出”做到,还有, ...

这个嘛,我有点不明白你在说啥....
if可以用多个命令方块朝向一个chain做到

然而我看不出这算是什么if,因为只要前面的给个信号那个chain cb,它就会执行命令,我看不到有任何条件。
else可以用多个“需要前面的命令方块成功输出”做到

需要前面的命令方块成功输出这不是if吗?为什么是else?

而且if那些相关的东西,你这里没说conditional,没说命令,没说红石组件,到底你想说什么呢?
作者: Cth_Can阿残    时间: 2015-11-7 00:22
vb大触说我不会编程_(:3」∠)_
作者: 719_Lokii    时间: 2015-11-7 00:33
没有end if能玩?没有select case能用?(斜眼
作者: 劫匪    时间: 2015-11-7 00:38
看到1/3的时候我就放弃了,看起来很腻害的样子
作者: 林扬骐    时间: 2015-11-7 07:16
pca006132 发表于 2015-11-6 23:52
这个嘛,我有点不明白你在说啥....

然而我看不出这算是什么if,因为只要前面的给个信号那个chain cb,它 ...

可能我也没有理会你的意思吧……
作者: 840196733mw    时间: 2015-11-7 12:25
本帖最后由 840196733mw 于 2015-11-29 08:43 编辑

看了半天,我想说,对于我还不如计分板呢(滑稽)
嵌套彻底看不懂了





————————————————————分割——————————————


在被计分板坑了之后回来看,终于理解了50%、






作者: chyx    时间: 2015-11-7 12:28
在reddit看过类似的
作者: pca006132    时间: 2015-11-7 12:53
chyx 发表于 2015-11-7 12:28
在reddit看过类似的

刚才Google了一下,你说的是https://www.reddit.com/r/Minecra ... ier_than_ever_with/这个吧?
这个我觉得最大的问题在于需要检测不同命令方块的successcount,如果是大量if else/嵌套的话,就需要检测不同坐标,这对我来说很麻烦(不能直接复制命令)。或者可以用AS来检测,然而还是麻烦,因为要指定每个CB一个AS,名字不可以相同,不然就可能会出bug。
作者: chyx    时间: 2015-11-7 13:15
本帖最后由 chyx 于 2015-11-7 13:17 编辑
pca006132 发表于 2015-11-7 12:53
刚才Google了一下,你说的是https://www.reddit.com/r/Minecraft/comments/3iuzs8/if_else_statements_ar ...

确实 你的auto确实十分巧妙
赞!我先不评分 因为我快9级了 到时候再评


作者: 白天    时间: 2015-11-7 13:25
支持下233
字太多233晚上再看233
作者: 玄素    时间: 2015-11-7 13:42
又大半夜码字23333注意休息
的确是蛮有趣也蛮有用的东西(关键是脱离scb简直好评)
作者: kongbaiyo    时间: 2015-11-7 16:25
满分满分!
极大简化√
作者: andylizi    时间: 2015-11-7 18:18
pca006132 发表于 2015-11-6 23:35
然而你就看了顶多3分钟吧。。。
这东西确实有意义的,解决了只能if不能else 的问题 ...

是的,代码太多实在头疼……果然1.9发布后,红石工程师/地图制造者要逆天了
作者: lorinder    时间: 2015-11-7 18:28
“例子: 如果有玩家叫a,就say 这里有个玩家叫a;否则如果有玩家叫b,就say这里有个玩家叫b;否则如果有玩家叫c,就say这里有个玩家叫b;否则就say这里没有任何叫a/b/c的玩家”
应改为:
“例子: 如果有玩家叫a,就say 这里有个玩家叫a;否则如果有玩家叫b,就say这里有个玩家叫b;否则如果有玩家叫c,就say这里有个玩家叫c;否则就say这里没有任何叫a/b/c的玩家”
作者: Neubulaeko    时间: 2015-11-7 18:30
哦?If和Else和Else if,不错嘛
*3 mins latre*
OMFG wtf have I seen such a complex I quit
作者: 秋一    时间: 2015-11-7 22:25
思路很棒,尤其是利用了auto:0在判定上几乎没有延迟的特性。不过对于入门的CBer来讲可能SuccessCount会更容易理解一些。

再有就是,我在思考一个问题,当这种嵌套被大量使用并且存在并联的时候,会不会由于符合条件的层不同而产生冲突。也许为了解决这个冲突,并联关系中同层的AS还是需要使用不一样命名,这样一来它的方便性时候会像testforblock那样打折扣?

然后就是testforblock在y方向分层可以比较好解决指令复制的难题,但是有个问题就是从里层往外跳的时候可能会有问题,我试着去从这个方向找找看能不能有一个很好的解决方法吧……

作者: pca006132    时间: 2015-11-7 22:32
acordome 发表于 2015-11-7 22:25
思路很棒,尤其是利用了auto:0在判定上几乎没有延迟的特性。不过对于入门的CBer来讲可能SuccessCount会更容 ...

那个嘛,估计常用的嵌套也不会超过10层,名字一般也不会超过10个,所以应该还是比较方便的。
至于testforblock呢,如果是在模组里使用的话,就需要根据不同坐标来testforblock(然而这只能在存档中使用,以OOC发给别人的话就不能如此使用),或者在CB的位置放置一个AS来execute testforblock,然而这样子名字更多也因此更复杂、麻烦。

那个,祝你能够寻找到一个更方便的方法吧(? ?_?)?
作者: :spgbigfan:    时间: 2015-11-8 13:48
本帖最后由 kakagou12 于 2015-11-8 13:49 编辑

十分精巧的设计!但是你怎么不丢中文译名=、=
作者: q1244705295    时间: 2015-11-8 15:56
【新人任务⑥】收藏精品{:10_517:}
作者: lzs1234    时间: 2016-3-11 23:03
喂我这不是挖老坟啊,只不过忍不住来回复了一下。
现在想起来我给你评分那时候还是图样图森破,当时其实我看了三分钟就看到一堆代码,然后我被吓到了评了个分就跑了。
之后稍微看了一些编程方面的东西,现在再来看这个基本不说100%理解也应该有90%了。
个人感想:当之无愧的优秀,很适合我这样的进阶中手看,auto用得很巧妙,充分利用好了CCB的bugfeather,希望多出点教程啊……
即使脑洞被狗啃了也得来点教程啊
作者: 840196733mw    时间: 2016-5-5 14:08
看完lzs1234 我发现这不是坟 可以回复

审核作品挂了 原因太卡 于是我又回来看这个帖子了  感慨 果然水平不够就觉得没有意义 进阶必须帖子

重新学习CB中