找回密码
 点一下
查看: 3373|回复: 17

关于这两天对自定义循环函数的研究以FOREACH为例

[复制链接]
发表于 2011-7-27 00:37:33 | 显示全部楼层 |阅读模式
这两天对自定义循环函数的研究以FOREACH为例,有些进展和大家分享下。

来了,首先来说说这个FOREACH函数有什么用,举一个例子,看我地图里面的函数我输入“7,8,9”的字符串,然后定义分隔符为“,”函数就会分别自动循环3次分别输出7、8、9并会执行里面的动作。当然有人说我把输出的函数COPY3个不就完了吗。不过你要考虑的是字符有可能100甚至更多,那还喜欢复制吗,而且要循坏的动作可能是多个的时候,你的代码不是又长又臭嘛。于是有改良的方法建立变量组,然后用FOR每一个组的元素来操作,不过这样还是要分开设置变量,要自己记数,还是要修改好几处,还是比较麻烦,而且还占用浪费了内存。于是更加完美的解决方法出来了就是FOREACH函数。你只需要修改一个变量就可以完成以上所有动作如例子中还有12、13、16要添加,那只要把字符串“7,8,9”改成“7,8,9,12,13,16”就可以,简单快捷,可读性强,不浪费内存。另外SE2中很多数据的属性都是以字符串的形式存储的比如单位ID,技能ID,科技ID等等,用这个东西可以简单的整合多单位,多技能的多动作处理。

先看看图,说明在2楼
2011-7-27 0-23-19.png
2011-7-27 0-24-42.png
2011-7-27 0-27-43.png

ForEach.SC2Map

18 KB, 下载次数: 32

评分

参与人数 1威望 +3 收起 理由
麦德三世 + 3 ~~~不错

查看全部评分

 楼主| 发表于 2011-7-27 00:38:41 | 显示全部楼层
沙发自己留

好了吹嘘一翻后,我们来看看到底是怎么实现这个动作
1、首先我们要建立自定义动作,这个时候我们必须勾选“循环”因为我们这个就是一个循环,而且没有循环的话不能用break。然后我们要再勾选子函数,只有勾选子函数才能在在在里面再添加函数。
2、定义动作后我们在自定义代码中加入处理的代码,代码的逻辑无非是根据字符里面查找分隔符然后取不同的字符,这里不作详细说明了。现在重点是你们会不会很奇怪那堆有#的奇怪的参数呢。这些在东西即使在Galaxy语法里面也是没的,这究竟是什么呢。。。。。。
别急偶们先来编译一下脚本对比了看。下面我抽取编译的部分和函数的部分来比较
#AUTOVAR(st,string) = #PARAM(strForSplit);
#AUTOVAR(len) = 0;
#AUTOVAR(f) = 0;
while (#AUTOVAR(st) != null) {
    #AUTOVAR(f) = 0;
    #AUTOVAR(f) = StringFind(#AUTOVAR(st),#PARAM(strSplit),true);
    #AUTOVAR(len) = StringLength(#AUTOVAR(st));
&#160;&#160;&#160;&#160;if(#AUTOVAR(f) <= 0){#AUTOVAR(f) = #AUTOVAR(len) + 1;};
&#160;&#160;&#160;&#160;#PARAM(strEach) = StringSub(#AUTOVAR(st),1,#AUTOVAR(f)-1);
&#160;&#160;&#160;&#160;if(#PARAM(strEach) != null){#SUBFUNCS(actions)};
&#160;&#160;&#160;&#160;#AUTOVAR(st) = StringSub(#AUTOVAR(st),#AUTOVAR(f)+1,#AUTOVAR(len));
&#160;&#160;&#160;&#160;if(#AUTOVAR(st) == null){#SMARTBREAK};
}
----------------我是分割线---------------

&#160;&#160;&#160;&#160;auto99773706_st = "7,8,9";
&#160;&#160;&#160;&#160;auto99773706_len = 0;
&#160;&#160;&#160;&#160;auto99773706_f = 0;
&#160;&#160;&#160;&#160;while (auto99773706_st != null) {
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;auto99773706_f = 0;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;auto99773706_f = StringFind(auto99773706_st,",",true);
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;auto99773706_len = StringLength(auto99773706_st);
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;if(auto99773706_f <= 0){auto99773706_f = auto99773706_len + 1;};
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;lv_tmpstr = StringSub(auto99773706_st,1,auto99773706_f-1);
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;if(lv_tmpstr != null){UIDisplayMessage(PlayerGroupAll(), c_messageAreaChat, StringToText(lv_tmpstr));
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;};
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;auto99773706_st = StringSub(auto99773706_st,auto99773706_f+1,auto99773706_len);
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;if(auto99773706_st == null){break;};
&#160;&#160;&#160;&#160;}

希望看完的人没有眼花,或者就直接来个感觉把,这两段语句结构是不是真他妈的像呢。
看第二句#AUTOVAR(len) = 0;和auto99773706_len = 0;噢发现问题了吗这个编译不就是把#AUTOVAR(len)变成auto99773706_len变量了吗,而且大家都有AUTO又有len字样。于是在看看后面的语句,规律都一样。难道说函数里面的是一个模板在函数编译的时候会用变量来替换吗。对,正解,就是这样。这里就是在编译的函数时候应用模板帮你自动写函数,你增加的动作会在编译时插入到模板你写有#SUBFUNCS(actions)的位置。例如上面的
if(lv_tmpstr != null){UIDisplayMessage(PlayerGroupAll(), c_messageAreaChat, StringToText(lv_tmpstr));
这个语句并会根据这个自动转换变量,其中auto99773706_len那个99773706是系统编译时自动生成的ID以避免变量与其他东西重名。

相不到SE2的编辑器还能自动滚动编译,实在太强大。GOOD

然后那具体这些#号参数代码是代表什么意思呢。(先开个会,回来再续,回来看到老大已经写了就不重复了直接引用)
引用第7楼麦德三世于2011-07-27 15:56发表的&#160;&#160;:
#AUTOVAR用来创建随机不重名的变量。第二个参数代表类型,可以忽略。类型可以由别的东西决定,比如函数的参数。
#SUBFUNCS用来代表sub-function里的内容。具体哪一行由关键字决定
#IFHAVESUBFUNCS判断是否有填写sub-function
#CUSTOM用户所输入的自定义代码
#PARAM用来取函数的参数
.......

OK现在函数已经搞好了,引用来试试
做好触发按F5发生事件
选择动作列表,一看OH赫然一个u_ForEachStr出现在动作列表里,原来自定义的函数会在动作列表中直接显示,以后引用可以不写代码了,可以直接拿来用了。实在太方便。哈哈,这又是比WAR3的一大改进。然后想怎么加动作就怎么加。
另外为了增强函数的通用性,附加了一个u_ForEachStrWithIndex的函数,因为考虑到抽取每个字符的INDEX的经常会用到,然后大功告成了。

到最后,大家看懂了吗?什么没有!!!!没关系,你只要把这两个函数COPY到你的地图中,然后直接在动作表里面挑来用就OK了,什么还不会用,那我也没办法了,写了这么多很累,下班走人。

(完)
回复

使用道具 举报

发表于 2011-7-27 10:00:41 | 显示全部楼层
看起来是个高端玩意儿~不过有图叉掉了拉~楼主注意下。
回复

使用道具 举报

发表于 2011-7-27 11:04:00 | 显示全部楼层
楼主同我一样 只有晚上翻屋企能测试啊,白天时间都浪费了,上班机器又不能用。
回复

使用道具 举报

发表于 2011-7-27 11:14:51 | 显示全部楼层
不错不错~~懂得怎么使用Sub-Function的人可不多呢~~

主要是那些宏~~
回复

使用道具 举报

发表于 2011-7-27 12:02:23 | 显示全部楼层
列一下几个宏

#SUBFUNCS

#IFHAVESUBFUNCS

#IFSUBFUNC

#PARAM

#AUTOVAR

#CUSTOM

#DEFRETURN

#SMARTBREAK
回复

使用道具 举报

发表于 2011-7-27 14:04:22 | 显示全部楼层
这些宏都是做什么用的呢?
回复

使用道具 举报

发表于 2011-7-27 15:56:25 | 显示全部楼层
#AUTOVAR用来创建随机不重名的变量。第二个参数代表类型,可以忽略。类型可以由别的东西决定,比如函数的参数。
#SUBFUNCS用来代表sub-function里的内容。具体哪一行由关键字决定
#IFHAVESUBFUNCS判断是否有填写sub-function
#CUSTOM用户所输入的自定义代码
#PARAM用来取函数的参数
#SMARTBREAK就是,当外部有循环结构的时候写break,反之不写。
#DEFRETURN代表外部函数的默认返回值
回复

使用道具 举报

 楼主| 发表于 2011-7-27 18:14:54 | 显示全部楼层
已经补完,各位可以再看看,给些意见。
回复

使用道具 举报

发表于 2011-7-27 21:25:37 | 显示全部楼层
循环遍历string,不错~ 可以和触发里的数据表结合使用吧,那个也是用字符串来存变量的
回复

使用道具 举报

 楼主| 发表于 2011-7-28 09:34:32 | 显示全部楼层
引用第9楼tazdingo于2011-07-27 21:25发表的  :
循环遍历string,不错~ 可以和触发里的数据表结合使用吧,那个也是用字符串来存变量的

对与数据表结合是最好的用法,偶就是这么用的,果然英雄所见略同
回复

使用道具 举报

发表于 2011-7-28 17:31:02 | 显示全部楼层
现在管理各种东西的时候有点纠结,到底是用变量好还是数据表好……

点评

纠结+1。主要是不知道那个效率高,直觉是变量,但是又不能肯定。  发表于 2015-4-12 23:35
回复

使用道具 举报

 楼主| 发表于 2011-7-28 22:51:23 | 显示全部楼层
引用第11楼tazdingo于2011-07-28 17:31发表的  :
现在管理各种东西的时候有点纠结,到底是用变量好还是数据表好……


使用频繁的当然是变量好,不经常使用当然是数据表好了。另外就是对于膨胀式的衍生变量那样最好就是数据表了,不然是无法管理。人脑是没法和电脑比得。
回复

使用道具 举报

发表于 2011-7-28 23:22:39 | 显示全部楼层
嗯确实是这样啊
另外数据表似乎动态存储和管理比较好
回复

使用道具 举报

发表于 2015-4-11 20:52:34 | 显示全部楼层
虽然这是个坟贴但是我还是要顶楼主一下,因为我之前玩WE的时候也巧合地用了和楼主一样的方法.
大概就是13年我做WE的物品系统的时候,因为用触发器模拟物品属性,而不同物品属性差异有很大,设置过长的参数表不效率也不方便,后来就用字符串来传递一系列不同的参数.
我把那个技术叫"字符之语",开始以为是自己独创,现在才发现原来楼主在11年就发明这个办法了!

现在发现Galaxy的DataTable也是在鼓励使用者巧妙使用字符串来提升代码的效率,对于使用了这种算法的用户来说真的是很容易就能理解掌握.

真的是后悔没有早点看到这帖子.

总之真的很激动,难得遇到想法一样的知音.

点评

用字符串传递多参数可能要追溯到电脑刚问世那会儿了。  发表于 2016-9-1 13:48
回复 2 0

使用道具 举报

发表于 2016-9-1 13:47:25 | 显示全部楼层
最近学习宏,为了方便翻资料,顶上来。不是故意挖坟,见谅。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 点一下

本版积分规则

Archiver|移动端|小黑屋|地精研究院

GMT+8, 2024-11-23 11:24 , Processed in 0.318738 second(s), 22 queries .

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表