| 文/523066680 2008-12-04 | | blog: http://hi.baidu.com/523066680 | | 批处理贪吃蛇首发地址:http://www.bathome.net/viewthread.php?tid=2038&extra=&highlight=&page=1 | | 本文在其20楼。 | | 个人单机电脑再次回到手上,也该对BatchGreedSnake分析一下了,描述能力和文采实在有限,希望不会浪费大家时间. | | 写本文的原因:再次看了cn-dos批处理精华帖 深受willsort精神的影响,太受鼓舞了,太神往了.现在开始写文章啦! | | | | 显示方式是定义几十行空行,然后用描点的方法显示蛇. | | (建立点的方式为 set y行=[y行 前x-1格]+[点*]+[剩下的格],因为点*就是在第x的位置上,所以前面是x-1格) | | | | 完成它的两大前提之一: 完成 随机游动的蛇 | | 之二: 突破批处理不能动态控制的局限.(在没有choice命令的情况下) | | | | 关于第一点,是我之前写了一个 随机游动的粒子,然后又进展成随机游动的蛇,随机游动的蛇其中一难,难在要控制蛇的长度, | | 完成了这点,我才相信我可以做出 纯批处理版贪吃蛇.(不控制长度就是在不断描点了) | | 关于控制长度,换一种方式思考会好一些,其实就是--在蛇往前移一个位子的时候,把蛇尾去掉.整个过程就是 | | 在不断的在蛇前面描点,去掉蛇尾的点.再清楚些吧,前面加了一个新的点,后面去了一个点,长度还是一样. | | 这点想来不麻烦,测试起来可就累,那个时候我个人电脑不在手上,去网吧完成整整花了十元. | | 怎么个难法? 比如蛇长10个单位吧,每进一步,就去一次蛇尾,那就是说要记录这10个坐标,前面增加一个记录 | | 的时候,把最开始记录的坐标去掉.所以啊,必须给它们编号1-10. | | 当出现11的时候把1去掉,难道让11 12 13...这些编号这样增长么?不行,干脆用1-10一直循环更替,前10个坐标后, | | 出现第一次更替--对第1个 第二次更替--对第2个……(同时去掉该编号坐标对应的点) | | 因为建立的点坐标先后就是按1 2 3 ...的顺序编号,去点的时候当然也是按这顺序了. | | 第一轮更改的1在第二轮更改时又是"蛇尾"了,于是就1-10 1-10的轮回了.而编号的排列顺序始终不变. | | | | 好,思路可以了,开始定义变量,给记录的坐标加上编号.像这样 set dot1=%x%,%y% 吗? | | 去点1的时候,就得对dot1变量附带的x y值分析提取,最主要是不知道是几位数,分析的时候又要下功夫,而且去点 | | 的时候百分号 感叹号 双百分号,乱就一个字. | | (去点的方式为 set y行=[y行 前x-1格]+[空格]+[剩下的格],就是原*变成空格,为何不直接set temp=%temp:*= % 呢 | | 蛇在同一行有其他点的话就全没了) | | 或许改改可以成功执行,但是我头晕,老出错……干脆换思路 | | | | 那就不分析,用set /a x1=x,y1=y 但是之后的操作是靠编号i的,x1的值这样表示!x%i%! 我觉得还是不爽. | | | | 于是就耍小聪明啊 -- set cut%i%="set /a a=%line%,b=%col%,c=%C2%" 这整个定义三个变量的语句都放在一个 | | 编号变量里面了,嘿嘿,利用批处理的性质,之后要用到这三个变量时,一句 !cut%i%:"=! 就相当于执行 | | set /a a=%line%,b=%col%,c=%C2% 接下来就直接%a% %b% %c%表示,而非!var%num%!或者%%var%num%%%. | | 对了,为何现在set里面有三个变量? 因为去点的语句中就是有y,x,x-1三个变量,这里顺便带上x-1. | | | | 感觉太good了,然后怎么判断蛇到了一定长度并开始去点? 建立变量 j=j+1 -->if j=10 则开始执行么? | | 缺点:1.j会一直累计 2.假如用if判断是否继续累计,则又多了一句命令,内存啊(不过现在还是100%). | | 所以我决定利用之前的编号变量i,一举两得.就利用if defined吧,这命令太good了. | | set /a 蛇长=10,i=1 | | :loop | | if %i% 小于 %蛇长% (set /a i+=1) else (set i=1) <----使得编号变量i始终在一定范围轮回 | | if defined cut%i% (statements) | | set cut%i%="set /a a=%line%,b=%col%,c=%C2%" | | goto :loop | | | | 继续打中文,中文哪里好?好在跟代码放在一起的时候不会混淆,好在我中文比英语好,为作为中国人而深感荣幸ing. | | 但仍需用中英两国语言继续向大家阐释思路,言归正传. | | if defined cut%i%句子在set cut%i%句子前面,充分利用了其先后性质,刚开始i从1-10 set 定义cut1-cut10 | | if defined 都是在set 之前执行,不会发现 cut%i% 被定义,跳过. | | 而第二轮,第11次循环,i=1时,if defined开始发现,之前set 在自己后面定义了cut1这个变量,他死定了,要制裁他! | | 于是就制裁了.在这之后if defined发现cut1 cut2 cut3……都建立了,继续制裁. | | | | (后传) | | 但是杀了一个cut 还有千千万万个cut 于是在if defined后面,set兄一直在重新定义cut%i%,cut%i%又活了, | | 并且赋予了新的意义.这种感觉就像"我们中国人民是永远打不到的!"(郑强的演讲视频看多了……) | | | | 详细: | | :::::::::::::::控制蛇长,判断是否建立食物部分 | | if %i% lss %long% (set /a i+=1) else (set i=1) <----使得编号变量i始终在一定范围轮回 | | if defined cut%i% ( | | if not defined dot (call :dot) <--若dot未定义则调用建立食物句 以dot变量是否被定义作为判断食物是否存在的标志 | | !cut%i%:"=! <--之前提到的编号变量.执行它相当于 定义 具有坐标含义的a b c变量. | | set "L%a%=!L%a%:~0,%b%! !L%a%:~%c%!" <--化该坐标的点为空,即去蛇尾 | | set "%a%_%b%=" | | ::去除坐标记录.这句作用大,与之后的set "%line%_%col%=exist" 对立 为if 判断提供条件. | | ::配合使用可用来判断蛇头是否碰到自身,防止食物建立到自身所在的坐标. | | ) | | ::::::::::::::end | | 对了,忘了if 里面是复合句,第一次建立的变量在句子后面并不会马上生效,要等到第二次循环时才... | | 所以去点的时间往后推了一步,而第一次时%a%无值,后面set 相当于执行 set L=...所以就没出错. | | 我也是刚想到,又要调试了……累。详细信息就不解释了,自己晕了,不想晕别人啊。 | | | | | | 关于第二点: | | 首先我是看了batman的随按随停的抽奖机,一个控制台 一个显示台,代码没细看,我猜是这样子的 | | 显示.bat 一直显示.并一直读取文件x的信息,并判断 当x的信息变成xx时,停止滚动项目. | | 控制台.bat 向文件x 发送信息. | | | | 不过batman那个好像没有生成文件,批处理也只有一个,我没时间了……临时分析思路凑合着用吧 | | 控制台:当用户输入信息并判断无错误时 执行echo,信息>x | | 显示台:时刻读取x的信息,分析信息并执行相应代码. | | 于是回家做足了思考,上网吧花了10元,才完成了初版. | | | | 过一星期,帖子有人加分,甚是高兴.发现wxcute兄的优化版贪吃蛇只用一个批处理脚本,估计思路如下,由于以前没想到 | | ,这里拿来分享下: | | | | 关于控制台,不用另外建立一个批处理,只需要把代码写到一个标签后面,用类似函数调用的方法, | | 实现:执行一个批处理,出现一个显示框,一个控制框,他们的功能不混淆. 代码简例: | | | | @echo off | | if "%1"=="yes" (call :direct) else (start %~nx0 yes) | | ::这里是显示台的代码 | | goto :eof | | | | :direct | | ::这里是控制台的代码 | | exit | | | | 是啊,这好像不难,而且很基础,但我想到了吗?没想到,所以这是一次不错的经验. | | | | | | -------------------------------------------留言 | | 这文章可能写的有些乱,啰嗦,代码也没怎么贴,只分析了主体思路,而且可能也没分析好.如果浪费了大家的时间,还请多多包涵. | | 我还是把想起的遇到的其他问题说出来吧,想了解又有耐心的朋友可以去看看原本的代码,分析一下. | | | | 控制台:假如上次输入w 如何防止输入s时重定向s到x ? 反过来呢? a 和 d 呢? | | (要是用户输入"上" 再"下"成功的话,蛇就可以倒着走了,这是错误,要防止.) | | 显示台:1.随机建立食物的时候,不能够建立在蛇所在的坐标,不能越过游戏框范围 | | 2.如何判断食物被吃了?需要用另外写命令--当蛇接触食物时去掉食物吗? | | 3.如何暂停并且继续保持显示暂停画面? | | 4.暂停后如何回到控制状态? | | 5.如何在暂停,正在玩,以及gameover时 使 退出 和 重玩 功能都能实现? | | : | | :COPY |
[ 本帖最后由 523066680 于 2008-12-6 10:56 编辑 ] |