幻想森林

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 3852|回复: 1

【狗尾续貂】关于存储变量的技巧

 关闭 [复制链接]

5

主题

90

帖子

1049

积分

⑥精研

NY极恶党首席苦力

积分
1049
发表于 2004-8-24 02:43:51 | 显示全部楼层 |阅读模式
     这两天没什么事儿,本打算贴一篇高效利用变量的东东,结果闲逛精华区时发现赫然有luolody大人的一篇“关于存储变量的技巧”……遗憾之余决定把用来研究的小例子发出来,算是对luolody大作的一点补充吧。

luolody讲的这种方法,基本上是一种时间换空间的策略

先补充一下用变量保存开关的具体实现方法

1、用变量保存二进制的一位状态,也就是用变量作为开关池

1.1、用到的变量

[img]http://bbs.rpgchina.com/attachment
/2004-8/200482424617165.jpg[/img]


V[5]:开关池
  把多个开关保存到一个变量里,有点类似于文件压缩,开关的状态就是文件,这个“开关池”就是压缩包文件(RAR、ZIP、……)。
  首先,约定1表示开关的ON状态,0表示OFF状态。
  RM的数字范围是从-9999999到9999999,开关只有2个状态,所以简单起见,我们舍弃负数,只利用从0到9999999之间的部分做开关池,精确一点说,我们只用从0到8388607之间的部分(理由见luolody贴)也就是二进制的111……111(一共23个1,也就是23位),这样就可以把1个变量变成23个开关使用啦。换句话说,RM的开关数量是5000,完全换用变量保存要5000/23=218个就够了(注1)。

V[3]:输入/输出
  在保存开关状态时用户把状态代入这个变量,写入开关的公共事件将把这个值保存进开关池里。
  在读取开关状态时用户从这个变量里得到读取的结果。

V[4]:开关索引
  因为是用一个变量保存多个状态,所以在读取/保存的时候,不但要给出值,还要给出在开关池的位置。参考luolody贴里的那个位数/位值图,从右往左(低位到高位)依次是第1、2、3、……、n位(我们这里n的取值是1到23这个闭区间里的整数,理由见楼主贴);还以luolody贴里的位数/位值图为例,右边第一位里的存放就是1号开关的值,在图里就是1,所以1号开关(注2)的状态就是ON;第二位是是0,所以2号开关的状态就是OFF,3号开关是ON;四号开关是OFF……所以如果想要读1号开关的状态,就要在V[4]里写上1;要写4号开关的值,就要在V[4]里写上4;

V[6]:临时变量;V[7]:计数器
  这2个变量都是在公共事件里用来保存中间结果的。

特别声明一下,为了简化代码(就是偷懒啦),V[3]、V[4]2个变量在调用完公共事件之后值会发生变化,如过还想继续用这2个值得话,请在呼叫公共事件之前把它们备份在别的变量里。

1.2、读取开关状态的命令事件

如图:至于每个步骤的意义,就是参照二进制的移位运算的基本原理,有兴趣得话可以查一查这方面的资料。

[img]http://bbs.rpgchina.com/attachment
/2004-8/200482421721744.jpg[/img]

命令事件的使用步骤
  1、写入开关索引,比如要读取1号开关就在V[4]里写入1,要读取2号就写入2,以此类推,一直到23。
  2、呼叫命令事件:“读取开关状态”
  3、从V[4]里读出开关的状态
  4、Over

1.3、写入开关状态的命令事件

如图:仔细看,其实写入的过程中第一步就是读取。只不过操作数不是放在同一个变量里罢了(为了避免冲掉用户输入的值,现在才觉得C的递归真是个了不起的特性,省了多少功夫啊)。

[img]http://bbs.rpgchina.com/attachment
/2004-8/200482421820839.jpg[/img]


  使用步骤
  1、写入开关索引,这个跟1.2的做法一样
  2、在V[3]写入要保存的开关状态。多罗嗦几句——1和2的顺序可调换;举个例子,如果要给1号开关置成OFF,就在V[3]里写入0(代表OFF),V[4]写入1(代表存放在1号开关里),如果要给3号开关置成ON,就在V[3]里写入1(代表ON),V[4]写入3(代表存放在3号开关里)
  3、呼叫命令事件:“写入开关状态”
  4、Over

OK,用变量保存开关状态的方法就大致完成了(注3),强调一点,以上的实现只是用来保存开关状态,就是luolody贴里面的“状态值为二进制的一位时”的那种情况。后两种情况,以后再说,方法是大同小异,而且因为不用作二进制——十进制的转换,过程反而简单。

注1、更精确一点的值是217.39130434782608695652173913043,^_^。不过这个贴给出的方法只是用1个变量保存,也就是只能保存23个开关,

想要用多个变量保存,请继续看注3。另外,虽然理论上可以用213个变量来保存5000个开关,但实际上在RM里是不可能用变量完全替代开关的,比如在“事件出现条件”这样的场合,RM给出了限制,只能用变量或者开关来判断。但是我们用的是开关池,也就是说,我们要判断的既不是一个变量的值,也不是一个开关的值,而是变量的值换算成二进制后一个位上的值(没有晕倒吧^_^),这个RM是万万做不来的。这样一来,这个方法的可用性好像就大打折扣了。其实呢,这个关键是看运用的场合了。还是举例说明,如果做一个事件,用分页的方式来代表不同的状态,那就没办法用到开关池了,象取完道具后开盖的箱子啦,或者吃完饭后空的碗啦等等。但是如果事件的不需要做分页得话,就可以用这种方法了。就像仙剑奇侠传一里N多隐藏的道具,说到这里想起当年转仙剑时唆使李逍遥挨门挨户挨墙角蹭东西的盛况了……扯远了。近处也有这样的例子,比如现在咱们论坛上最受欢迎的“瞳孔”,淳一开场跑到别人家里“上班”,就从那些不起眼的地方搜东西出来,其实能开盖的箱子,也可以不用分页就做出来……,又扯远了。最后强调一点,如果5000个开关够用得话,当然就犯不上用这种节约闹革命方法来做了,那纯粹是浪费时间!

注2、这里说的1号开关,不是指RM的那5000个开关的第1个开关,仅仅代表开关池里的第1个开关,下同。

注3、读取/写入事件都用到了一个叫“索引换算”的命令事件,这个事件是把用户指定的开关换算成算法内部的索引表示方法(还是跟移位运算有关),可以近似地认为那是一个散列函数。注1里提到的用超过一个以上的变量来做开关池,做法就是改这个“索引换算”事件的实现,使之能够从多个变量里唯一得确定那个二进制位的位置。

如图:索引换算的实现

[img]http://bbs.rpgchina.com/attachment
/2004-8/200482424043368.jpg[/img]



[此贴子已经被作者于2004-8-24 2:46:52编辑过]
毋意,毋必,毋固,毋我
回复

使用道具 举报

330

主题

3719

帖子

5万

积分

⑧专业

霄月破苍穹

积分
58690
QQ
发表于 2004-8-24 10:21:36 | 显示全部楼层
写的不错,辛苦了
噩梦刃化
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|幻想森林

GMT+8, 2024-5-6 07:26 , Processed in 0.026042 second(s), 21 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

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