彪悍的新手
本帖最后由 彪悍的新手 于 2017-7-3 15:04 编辑


前言

调用自身的操作叫做递归
本贴讨论较为基础的递归操作
(本帖将一串命令方块看似一个函数)
(部分图片来源网络,如果侵权请联系本人删除)


2021.12 数据,可能有更多内容


前言


调用自身的操作叫做递归
本贴讨论较为基础的递归操作
(本帖将一串命令方块看似一个函数)
(部分图片来源网络,如果侵权请联系本人删除)





在函数尾部的递归


这个就像是首位相接的的命令方块串
实现的方式有很多种
跳出递归可以使用scb来判断次数或者更多的条件限制
譬如这样

代码:

  1. /scoreboard players test @p f 0 100
  2. /setblock x y z redstone_block

与其说是递归
不如说更像是for循环






更加复杂的递归


如果我们可以在mc中画一个二叉树,那就不是很好办了。



先从简单的想起
例如一个在“函数”中部的递归
先执行完前半部分,然后执行递归
然后执行后半部分
例如下图

最后再执行尾部
从图上可以很好看出执行过程


然而这样会遇到一个问题

例如图上红圈处是递归部分
而当第一次执行到这里时
第二次就开始了
第一次执行到下一个时
第二次才执行到第二个CB
显然不符合要求
而且一旦执行次数多
就有BUG的可能性
所以这种情况下
必须只有在前一个函数彻底执行完毕才可以继续往下
可以将函数分段,分为递归前和递归后两段

多增加一些判断来进行回调
只有模拟计算机中函数的操作才可以
每当函数被调用
申请一个空间
函数调用结束时,
删除空间
也就是说用类似clone的命令将整个CB串复制
然后再执行
也许有人会问,那样的话复制的位置怎么办
可以用如盔甲架这样的实体一个一个的复制(execute)
然后调用结束时同时删除盔甲架和临时的CB串

代码:

  1. 函数头:
  2.     压入栈;
  3. 函数中段:
  4.     执行任务;
  5. 函数尾:
  6.     弹出栈;



  7. 递归:
  8.     申请新栈;
  9.     将下个函数压入栈(重复函数头);






形式参数的传递


很显然递归中有一个参数在传递
这里可以用一个计分板中的各种盔甲架的分数来传递
用scoreboard players operation来操作
最后刚好可以把盔甲架来删除


Tips:标记一个计分板可以使用先后出现的时间来操作,如果递归在函数中不多(≤1)的情况下可以采用每次召唤新盔甲架时分数+1,然后第一次就是1,第二次就是2……这样可能可以做到(伪)地址传递。如果递归较多,那可能只能表示一次节点上的所有盔甲架。





其他可能实现的方式


前面讲到利用/clone来操作的方法
现在我发现一种(似乎)更加优秀的方法
但是还有点未知的地方
比如如何回调还是没有准确的方法
就是让盔甲架之类的实体召唤更多的盔甲架,然而删除自己,让其他盔甲架执行命令
适合简单的(伪)递归操作





后记


由于各种懒癌,本人暂时没有成品,但是理论上是可行的,如果有其他的想法希望能通知我一声XD。
可能具体制作起来还是有一点困难,希望各位大佬多给点意见。


@LBL_CB @阴阳师元素祭祀 @MsYqgzt @乙烯_中国 @FHC红石

pca006132
本帖最后由 pca006132 于 2017-7-3 14:48 编辑

我看到函数还以为是说的命令函数(function)...

其实命令方块的递归还是把递归变为stack + 循环比较好...把分数、当前状态放进stack里然后循环下一遍,那样就不需要那么多组cb了。
至于暂停的部分可以利用auto:0b,用marker execute的话还是比较方便的
毕竟cb不是编程,cb优化不代表编程优化,编程优化不代表cb优化,申请空间啥的不是所有人都知道,也没必要说得那么复杂


langyo_v3
其实……你只要实现一个只暴露接口的栈不就好了?

归燕
表示完全看不懂
楼主真的很6
这是真心话
我自认为我没有在水

QAQda
好东西=0=