易码技术论坛

 找回密码
 加入易码
搜索
123
返回列表 发新帖
楼主: 一捧米

[技术文章]将BAS程序简化进行到底!!!

[复制链接]
 楼主| 发表于 2007-7-11 22:38:05 | 显示全部楼层
感动ING……
我现在就去看~
发表于 2007-7-11 23:08:17 | 显示全部楼层
??LZ知道我编的什么??我编的东西并不多啊,到易码混了这么久,都没什么大的贡献...惭愧ing
唉,我觉得那个作图工具的实用性并不差啊,为什么在GGV的论坛里面竟然一篇回复都讨不到?太伤心了...
发表于 2007-7-12 09:37:05 | 显示全部楼层
引用第42楼xp12342007-07-11 23:08发表的“”:
??LZ知道我编的什么??我编的东西并不多啊,到易码混了这么久,都没什么大的贡献...惭愧ing
唉,我觉得那个作图工具的实用性并不差啊,为什么在GGV的论坛里面竟然一篇回复都讨不到?太伤心了...
ggv?
那帮小屁崽子就知道玩,都天天想着用星星玩电脑游戏!!
梦幻嬉游,
反空精英,
流星蝴蝶剑!
 楼主| 发表于 2006-10-18 13:15:29 | 显示全部楼层 |阅读模式
PS:之所以将PS放到前面,是希望管理员不要移动我的帖子,因为去BASIC专区的人毕竟是少数,而我希望更多的人们能看看我的帖子。我不求加精,但希望置顶,因为文章中说的那种人太多了。
首先,我要声明一下:这个帖子主要是给那些BAS新手或中等水平的人看的。这并不是说我是个高手,而是我实在看不下去了,忍不住跳出来说两句:各位BAS写手们,请你们简化一下你们的程序吧!我知道你们不怕手累,但是……超过16K的文件在WQX上没办法改啊,想加个POKE 29943,255还要用PACMGR,我受不了啦。还有,看到那么多的IF...THEN...我实在想把WQX砸了。我想,还有许多与我同样想法的人吧?
也许你们不会简化(这也没什么,我在一年前也不会);也许你们知道一些,但用得不好,甚至嫌麻烦;也许你们根本不在意,或是用做好的游戏引擎时懒得改,但是,只要你还热爱BAS,我奉权一句:老大,简化一下吧!
我的这篇文章,仅是一些小技巧,但惭愧地说,我知道的大概也不全。所以,若是哪位高手还知道更多更好的简化法,欢迎指正。
⒈IF...THEN...的简化
这条语句,大概是大家最常用的,而且也同样是大家写得最繁锁的语句。所以我放到第一个来谈。
举个很简单的例子:
10 K$=INKEY$
20 IF K$="b" THEN xxx
30 IF K$="n" THEN xxx
40 IF K$="m" THEN xxx
...
...
...
这些语句相信所有人都见过,就是简单的按键判断语句。但是有一点我不明白,为什么要用那么多IF...THEN...呢?在易码混了这么久,连它的简化也不会么?
去翻翻BASIC专区的置顶帖,你就会发现,其实这个最简单:
10 K=ASC(INKEY$)
20 N=(K=98)+(K=110)*2+(K=109)*3
30 ON N GOTO X,Y,Z...
这个方法绝对早就发明了,但看过最近几个新出炉的BAS游戏,前一种的老式方法却仍占主流……
前面的例子只是个引子,我要说的主要在下面。
同样用例子说明:
10 IF A=1 THEN B=3 ELSE IF A=2 THEN B=6 ELSE IF A=3 THEN B=9...
看了这个例子,不要笑,你也许认为自己不会犯这种笑话,但如果换成下面的例子呢:
10 IF A=1 THEN B=2 ELSE IF A=2 THEN B=3 ELSE IF A=3 THEN B=2 ELSE IF A=4 THEN B=3...
这种情况怎么办呢?就这样处理?还是可以简化?
答案显然是后者。
10 B=2+(A/2=INT(A/2))
这样不就简单多了?这还只是个简单的例子,若是更复杂呢?其实只要把握一个原责:尽可能多地使用函数,对于多次使用的函数,应该用自定义函数(DEN FN语句,这里比如为了加快反应速度的即时型游戏,若用跳转语句会减慢速度),对于应用一次的公式就用Y=kX+b模式。在表达式中,找出数据规律,多用用INT、SGN等语句,绝对比平时作数学题简单。同时要注意,尽可能地写出最短式,这和平时写的函数最简式不是一个概念,很简单的例子:BAS的语法里,乘号不能省略。
这里提供一些必需掌握的语句:ABS,INT,SGN,SIN,SQR,SWAP,STR$,VAL,NOT,()。
看到这儿,相信你的眼睛:最后一个就是括号。
不用奇怪,括号,在大部分情况下,都可以作IF...THEN...语句的最好替换者,这样便节省了大量IF...THEN...语句的使用——看看第一个例子。
结语:IF...THEN...在一个成形程序中绝对必不可少,但怎样少用它才是关键要掌握的。不然,你就会看到类似《校园历险记》(好象是这个名字,我记不大清)中,10几20多K的程序,差不多一半是IF...THEN...,程序大得要死,容量少得可怜。这里不是点名批评,只是抓个典型,作者见谅。

⒉数据规划
我在这儿不是教怎么数规,而是教怎么合理数规。
我见过很多不合理数规的程序,其特点是各种属性的数据用了一大堆(尤其是RPG游戏),数据间关联甚少,或是顺序乱七八糟,最后要应用的时候没办法,只好写一大堆的IF...THEN...。
数规的好坏和上一章IF...THEN...简化法中函数表达式的简化有很大关系。比如你有时可能会发现:一组数据之间的转换,怎么也写不出表达式。那么,我可以明确的告诉你,你的数据编排有问题。
怎样优化数据?同样很简单。我举个例子:
我写过一个游戏策划案,RPG游戏,三个职业:剑士、法师、弓箭手。要按一般的办法,他们的各种属性,只能逐个罗列,升级时,还要跟据职业特点,设三种属性加法。
天呐,我被这种想法吓了一跳:这怎么处理?要按这样,16K的程序显然不够写,要知道,我的想法里,一个人是有血、魔、攻、防、敏、幸运等一堆属性。
怎么办?是减少数据,降低游戏容量?还是用大量的IF...THEN...?说实话,我这个游戏的初衷就不是要以剧情为重点的,如过去掉各种数据,那这个游戏跟本就没玩头了。而我又实在没耐心写那么多IF...THEN...
那只好找规律。
我们来看:剑士血高,防高;法师魔高,攻高;弓箭手这四项正好介于两者间。既然如此,我便把职业编号为:⒈剑士,⒉攻箭手,⒊法师。这样,不就可以每项属性只用一个一次函数式来代表了?升级时,还可以用同一个公式,只要把属性公式设为关于等级和职业的二元函数(不知还算函数不),这样一下又省了一半公式,还可以合理程序结构(关于这点,下面会讲)。
结语:总结来说,就是在规划数据时,尽量形成规律化排列,以便写函数表达式。不同数据间尽量形成链条,不要各管各的,简单来说,就是减少直接赋值的数据,而是使用已赋值数据用函数生成新数据,就像我的例子中,最终人物各个属性只用到两个已赋值数据:职业和等级。
⒊程序结构
什么是程序结构?就是程序脚本中语句的编排顺序。
你也许认为这不重要,但其实合理的顺序编排同样有助于简化程序。
比如:一个程序中有N多个子程序,但你会发现,其中必然有几句是重复的。不是子程序的重复,而是其中的某个函数,或是某条判断语句。但这时,两个子程序“分居两地”,根本没办发把其中共同的部分和用,怎么办?的确有些程序里把这些常用句专门做成另一个子程序,然后GOSUB调取,RETURN,再RETURN。那么你算算,就这两个RETURN和GOSUB就占去至少17个字节,还不包括前后的行号,算来算去,你节省了多少语句?
那好,来看看我为解决这个问题而写的一个程序规范化模本
0 :
1 GRAPH:GOTO “主程序”
5 RETURN
10 子程序1:GOTO 5
20 子程序2:GOTO 5
30 子程序3:GOTO 5
...
...
再后面更多的子程序和一个主程序怎么写,我不管你。但按这个模本,可以解决上面的所有问题。
为什么这样做?听我慢慢解说。
首先,第0行是给程序员用来跳行的,你恐怕不想“输入”键很快就坏吧?第1行放GRAPH是我的习惯,当然你也可以放别处。第2、3、4、6、7、8、9行是预留空间,防止以后要加语句(比如POKE 29943,255)。第10、20、30行只是个象征,具体行号取决于子程序的大小,但要把所有子程序放到主程序前。
关键是第5行的RETURN。
大家应该都知道,RETURN语句的脾气比较怪,把它放到语句末尾总会出现ERROR:RETURN WITHOUT GOSUB。我至今也没弄懂怎么回事,因为我确实见过把它用在末尾的程序。也许这是个BUG,也许是别的什么原因,我们都还是不去管了,只要“曲线救国”就好。
那么,把RETURN放到第5行就是我的方法。你会发现,GOTO 5和RETURN所占字节数一样,不同的是,GOTO 5可以放心大胆的放到语句末尾而决对不会打绊子。这样一来,就可以省下行号这2-5个字节。不要小看这么点儿数,数数你的程序用了多少个RETURN,再乘乘看。更何况,若是把它放在IF语句后时,连GOTO这5个字节都省了(别忘了空格的一个字节)。
然后,你还会发现一个有趣的事实:整个程序,只用了一个RETURN语句!
最后,关于子程序合并的问题,我在这里只提供一个概念:专门选几个单个字母作临时性参数变量,把重复部分的计算语句都用这些参数完成,这样便形成一个程序组件。用时,把数据带入参数,然后完成计算,返回。
我之所以不强调这个方法,是因为你得看具体应用,不要得不偿失。还提供一个提示:这里会用到SWAP语句。
这种方法,就好比原来的子程序像品牌机,虽然方便,但不一定好用,最多加几个配件;现在好像组装机,用什么,装什么,变化多。唯一的缺点就是规划时废脑子,但我想喜欢编程的人脑子一定都很好用吧?
结语:程序的结构规划至关重要,不仅简化了程序,而且,你还可以避免犯下面我要提出的几处错误。同时,我可以透露一下,用我最后提到的那种理念,我已经成功的把一个程序中所需的所有按键响应(包括人物行动、选择、光标移动等)集中到了一个子程序组中,你也可以试试。
⒋图型控制
这是一个综合性的问题,其包涵了上面所有的三章内容,我这里只具体地谈下应用中应注意的问题。
首先是RPG中人物的行动问题。我要说,我见过许许多多种人物行动方式(语句),不外乎都是应用人物座标变换的原理。但刨去主程序影响的问题,各种方法中人物移动速度还是有不小的差别。这里当然不是说在屏幕内的移动速度(其实还是有差别,这里暂不提),而是换地图时的速度。
造成这种差距的,当然还是程序本身的问题,其包括上面三章的所有内容。
当然,我没办法在这里一个个具体分析,只推荐一个我认为最优的案例:《大航海时代Ⅰ》中绘图及人物行动判断法。
你也许会说:这和我的方法也无太大不同。但注意,我推荐的,主要是他的绘图法。
这个方法的发明也有些日子了(至少两年),可在后来的许多正常格(20*5)地图中,却没有见到比这更好的绘图法。而他的绘图法、读图法、人物移动法是一套的,因此必需合起来用。其实这就算一个地图引擎了。
这种方法里,可以完全避面因防止大量数据处理而造成的地图过于单一,同时保正数据总量少,语句简单、易懂。
当然,并不是说这个引擎完美无缺,其中最大的一个缺点就是一张小地图的屏幕边缘若是可行动区,临张小图的对应边缘也同样要为可行动区,不然就会出现人物移动到非可移动区的BUG。这样无形中便浪费了地图容量。其实也很容易解决:只需在原有基础上增添2个参数便可。而且程序中也犯了不够简略的毛病,对照上文,我经过优化后,大约减少了1000个字节左右的大小,全部读、绘图及行动语句只剩不到2000个字节左右。(注:由于此文件创建时间较早且早已丢失,具体文件大小以实际为准,但内容皆为试验通过结果。)
第二个小点是文字显示。大部分人在文字显示中只用到PRINT和LOCATE语句,然后文字出来时闪烁不说,这两个语句还被反复用来用去,按照上一章末的概念,这不就属于重复语句么,也就是说,我们完全可以简化。
这里,就要用到POKE作图法。
上面的地图引擎中,就用到了这个方法,于是,我们还可以把文字显示嵌入其中,具体做法我不细谈了,我只来说说这种方法的优点:
作图法中,显示过程是先把图像或文字换成ASC码,然后用FOR...NEXT...加POKE把图像(文字)打到内存里,PRINT显示。
你也许觉得麻烦,但别忘了,这是个子程序,只用写一遍!
最后,主程序中的文字显示,就可以这么写:
5 RETURN
10 (显示子程序):GOTO 5
20 A$="ABC":N=31:GOSUB 10
N=31是屏幕由上至下输出的位置,看看原来应怎么写:
10 LOCATE 2,11RINT"ABC";
没发现两者的区别么?前者可完全不受自动换行的困扰,也就是说,你可以在屏幕右下角显示文字。同时还可以很方便地做出“居中”,“判位显示法”(就是RPG中,人物处于前三排时文字显示于屏幕下方,ELSE显示在屏幕上方)等多种文字特效。
你也许会说不够简略,那你还是在程序中用用吧,用多了就明白了。
我这里再强推一个文件减肥法,还是看《大航海》。我真的蛮欣赏这个方法:
把所有的文字,包括菜单,全部放进.DAT数据文件。看看《大航海》的大小,在没有简化到极至的情况下,主程序比数据文件.BAS还小。
最后是动画效果。
我在这里说的不是简略法,正相反,我要说的是扩充问题。
大家的美工也许好,也许不太好,但没关系,有别的方法可以弥补这种不足。
我以《百战天虫》这部作品为例:首先要说,我实在很喜换这部作品,但同时,我还是找出一些细节上的不足。
比如:游戏中所有“虫”的攻击范围和爆炸范围都是固定的。这乍一想没什么,但再想想,如果把这些数据与虫子的其他属性挂钩,又会怎样呢?毫无疑问,增加了游戏的变数。变数越多,游戏的可玩度越大,这样一来,不就是在不大量增加语句的情况下,无形地增加了游戏容量。物尽其用,本身就是简化法。
再比如:电脑上的《百战天虫》游戏中虫子死后会留下墓碑;水面上方是波浪状;武器系统里最好用的是“超级绵羊”等。这些效果要在BAS上实现很容易(我都实现了),就不过几条语句而已。不要小看这些细节,把每个细节都做好,你的程序才会显得精致。
结语:图形处理的过程中,要把握几个原责:“惜字如金”,注重细节,合理分配,合理绘图。尤其注意不要画太多华而不实的动画或效果,要明白:BAS的美工再好,也比不上LAVA。要以美工与系统通的良好契合做为好程序的最终目标。
5.严禁废话!
几乎在所有程序中,都不同程度地存在“废话”问题。什么是废话?就是其有无对程序毫无影响的语句。
出于某些原因,我对那些废话太多的程序实在难以屑于一顾。当然,对于新手们由于入行不久懂的太少而产生的无用语句,我到是非常乐于加以指导的(同样希望大家都对他们加以指点),但如果你入行一年以上却还在写大量废话的,你应该脸红。
我在这里会将我所知道的所有无用语句一一列举。
先针对菜鸟们说几条,非新手者跳过:
1.IF语句末尾GOTO xx中GOTO语句可以省略。还有,IF的后面不用写XX=1或XX=0,因为IF的默认判断“通过”数值就是1,“不通过”数值是0。所以可以善用NOT语句,IF NOT的默认判断和IF相反。
2.所有变量的默认值都是0,所以不要赋值A=0等。当然你看到某些程序中有A=0000也不要奇怪,那是为了数据占位。
3.这是一个很少有人会犯的错误:LOCATE 1,1,但我确实见人这么用过(非回复光标而用)。我在这儿提它的原因是想告诉学习语言的人们:光看教程,把语言含意背得再熟都没用,自己亲自把每条语句都用一遍(当然除了POKE和CALL),才能知道它的具体用法,才能够想办法简化语句。这和光听课不做题怎么也学不会是一个道理。
4.这个也许不是新手才有的毛病:语句太散。就是没有把可放在一行的语句放一块儿,但新手要注意,有两种情况语句必需分开:一、IF后的语句,这里指不论前面IF是否成立都要执行的语句;二、RETURN语句,这句只能单独做一行,但看完前文你就可以忽略这个问题了。非新手看完不要笑,我还是小菜时就经常为这两个问题而苦恼不知哪写错了。
其次是NEXT的使用,来看例子:
10 FOR A=1 TO 100:FOR B=1 TO 100
20 NEXT A:NEXT B
这也是大部分新手都会犯的错误,然而我发现,不少水平还不错的程序中也会出现这种写法:
20 NEXT:NEXT
其实这样就不错了,但最简写法是这样:
20 NEXT A,B
明白了?虽然只省了一个字节,可一分钱也是钱啊!
再次是关于重复定义。
这不算是个错误,只能算个失误,但由于比较普遍,我还是不得不一提。
出现这个失误正是由于上文提到的程序规划不合理而导致的,其表现是一个数据在几种不同情况下需划分处理时,被几个相似或完全一样的计算式处理,而出现的语句浪废的情况。
但其实只要细心,或是合理规划程序,这种状况就完全可以避免。
最后,也是最普遍的一种废话,就是各种变量的变量名。
我见过一个废话到极致的程序,里面所有的变量名都用其代表的数据含意的英文或拼音全称来代替,比如经验:EXPERIENCE=xxx
我好想问那个作者:你累不累?
这个可以当笑话讲,但你写的程序里就没犯他的错误么?
我想大部分人都犯了。为什么?因为我认为,写两字母以上的变量名就是浪废。
我们算算,两个字母的名字有26*26=676种,你的程序再大,也用不了这么多变量吧?
你也许会说:用多个字母是为了编程时好记。但你既然可以写这么大的程序,为什么懒得拿张纸把所有变量名代表的含意写下来以便随时对照呢?一时手懒,造成写程序时要写更多的废话。
你也许还会说:这是为了方便读程序的人好认。
但既凡程序员,都是靠程序来推敲变量的含意的,而不会去研究你那几个不知是英文首字母还是拼音首字母的变量名。
结语:从废话的多少,完全可以看出一个程序员的优劣或认真程度。希望大家还是多多注意语言的简洁为好。
总结语:我所了解的程序简化方面的知识,差不多也就这些了,也许还有些我一时想不起来的,日后会补充上去,也希望高手们能提供更多的方法加以充实。
其实不论什么语言,都有其自己的语句简化方法,我在这里不光面对BASIC写手,也提醒那些LAVA写手们,简化程序也是项技术活,如果想让你们的水平有所提高,如果想让你们的程序更加精致,简化程序,绝对是一条必经之路!

BAS简化法.txt

13 KB, 下载次数: 626

BAS简化法

您需要登录后才可以回帖 登录 | 加入易码

本版积分规则

Archiver|手机版|小黑屋|EMAX Studio

GMT+8, 2024-4-20 04:33 , Processed in 0.012031 second(s), 20 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

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