该手册由 gitblock.cn 上的一位用户 -6 撰写。
其用户页链接为 https://gitblock.cn/Users/1099557。
为方便分享,我将文章转载到了这里。

目 录

  1. 前言

1-2 ...
3-5 ...
6 ...
附录

附录1. 绕过角色的大小和位置限制
附录2. 避免矢量图造型边界模糊
附录3. 使用广播代替绿旗,让调试更加方便
附录4. 更加友好的按键判定
附录5. 判断按下停止键
附录6. 广播、循环、克隆原理猜测
附录7. 碰到颜色积木能接受的误差
附录8. 回答被打断的特殊情况
附录9. 排查自己的程序卡在哪里
附录10. 把txt文件转换为csv文件的转换工具

__0__. 前言

这个手册主要是给接触过Scratch 3.0但是对一些情况感到迷惑的人们看的,如果你想要入门指南,可以直接点击“教程”按钮查看Scratch自带的教程,他们会告诉你如何使用基本积木制作简单的游戏。
Scratch很简单,很容易上手。但Scratch又很不简单,有一些特性和技巧你未必了解。在不完全了解Scratch的情况下,凭感觉拖动积木形成程序,会让你的作品遇到越来越多的坑。我会尽量把内容做的简洁,希望大家能够避开坑,学到更多创作技巧,少走弯路。
内容中有对拓展,二创编辑器,社区的推荐,这些内容只是因为其对创作的确有帮助。
有【需要考证】标记的内容表示这个内容没有经过严格实验证明。

这不是官方文档,只是个人的猜测。一切以Scratch真正的运行结果为准,因为只有实践才能出真知。

如果你发现了文章里的错误,请在评论区回复,非常感谢!

附录1. 绕过角色的大小和位置限制

首先,准备2个造型,一个记为A,什么都没有:一个记为B,用一个矩形填满(不要超过边界!)
然后,如果大小需要设定的大于100,换成造型A,否则换成造型B,然后设定大小,这样大小便能成功设定。再换成需要的造型即可。
至于移动角色到任意位置,先换造型A,大小设成10000000,再换造型B。此时角色会非常大,可以大范围移动。当然太离谱的不行
最终的积木如下图:
%%%

附录2. 避免矢量图造型边界模糊

在造型旁边画一个透明的框就可以了!
%%%

附录3. 使用广播代替绿旗,让调试更加方便

可以把所有的绿旗积木替换为“当接收到[启动]”,然后在背景里面加一个“当点击绿旗时:广播[启动]”,在调试的必要的时候,你可以通过改变[启动]任意选择广播起点,并且能够在调试完之后方便地恢复原样。
还可以在每个角色加一个“当接收到[停止]”,后面依次接上“停止所有声音”“清除图形特效”“清除音效”“停止该角色的其他脚本”“删除此克隆体”,这样子广播“[停止]”之后可以模拟点击停止键。
可以通过建立一个空角色,在里面放入“当接收到[重新开始]”“广播[停止]并等待”“广播[开始]”(这个角色里不能有“当接收到[停止]”和其他积木),这样广播[重新开始]就可以模拟点击绿旗,免去部分情况下需要用户点击绿旗的烦恼。如果需要重置定时器,可以加一个计时器归零。需要清空回答内容就没办法了。

附录4. 更加友好的按键判定

如果只是使用“当...被按下”积木,很容易遇到操作别扭的情况。
使用“重复执行...”“如果 按下 ... 键”可以避免这种情况。
另外如果想让“当...被按下”只捕获按下瞬间,忽略按住之后的响应,只需要在最后面加一个“等待 按下 ... 键 不成立”即可。

附录5. 判断按下停止键

使用计时器就可以判断停止键的按下。
比较简单的方法:
当点击绿旗时,设置变量 x 为 -1 (不触发),
当收到广播[判定停止键]的时候,循环设置变量 x 为 计时器 (准备触发),
当[计时器] \> (x) 的时候,设置变量 x 为 -1,然后执行停止键按下后的积木
原理:一开始 x 被设为 -1,第三行不会触发;
广播[判定停止键]后,循环运行,x一直等于计时器;
按下停止键后,循环被打断,然后随着时间流逝计时器会立即大于x,触发第三行;
之后把计时器设为 -1 防止重复触发。
这个时候按了停止键就真的停止了。此时可以继续广播[判定停止键]判定下一次停止键的按下。

附录6. 广播、循环、克隆原理猜测

Scratch 的广播和循环让我们感到莫名其妙,是因为我们不了解它的运行原理。
如果我们能够通过实验来猜测其原理,我们也许就能够更好地使用广播和循环制作更加可靠的程序。
我是在 TurboWarp 上测试的,关闭了编译模式,我猜就算打开编译模式结果也还是一样的【需要考证】。大家也可以下载文件自己用自己喜欢的网站或者编辑器测试。文件下载地址:【需要考证】

不想看分析过程的可以直接看 粗体字部分 或者最后的总结(搜索“循环原理总结”)。

循环

在Scratch中,循环在运行的时候会被限制速度,每秒三十次,而且有可能会有多个循环在同时进行。在编程的时候你可能就会想到:两个循环一起修改一个变量会不会出问题?这些循环会不会一个快一个慢?广播会不会损耗时间?接下来让我来为大家提供一些测试的结果,让大家了解一下Scratch可能的处理循环的方式。

先从简单的例子开始:(文件名:同步1.sb3)

当点击绿旗时
重复执行
| 把 “1” 加入 [测试列表]
\------/

当点击绿旗时
重复执行
| 把 “2” 加入 [测试列表]
\------/

清空测试列表,点击绿旗,可以发现这两个循环运行地飞快,但是列表中居然是富有规律的

1
2
1
2
1
2
...

和想象中乱序的并不一样。
再复制一个循环,2改成3试一试,会出现什么呢?
答案是:

1
2
3
1
2
3
...

可以看到:Scratch在同时运行多个循环的时候,是按顺序运行的!
有没有一种可能,这是因为三个循环里都只有一个积木呢?
我们再给它加点花:(文件名:同步2.sb3)

当点击绿旗时
重复执行
| 把 “1” 加入 [测试列表]
\------/

当点击绿旗时
重复执行
| 把 “2” 加入 [测试列表]
| 把 [变量1] 设为 平方根(变量1 + 1 / 变量1)
\------/

然而列表中仍然出现有规律的 1 2 1 2 1 2 ...

再加一个:

当点击绿旗时
重复执行
| 把 “3” 加入 [测试列表]
| 把 [变量1] 设为 平方根(变量1 + 1 / 变量1)
| 把 [变量1] 设为 平方根(变量1 + 1 / 变量1)
| 把 [变量1] 设为 平方根(变量1 + 1 / 变量1)
| 把 [变量1] 设为 平方根(变量1 + 1 / 变量1)
| 把 [变量1] 设为 平方根(变量1 + 1 / 变量1)
| 把 [变量1] 设为 平方根(变量1 + 1 / 变量1)
| 把 [变量1] 设为 平方根(变量1 + 1 / 变量1)
| 把 [变量1] 设为 平方根(变量1 + 1 / 变量1)
\------/

列表中仍然是有规律的 1 2 3 1 2 3 ...

因此可以猜测:在 Scratch 中,循环的同时进行,是通过把每一个循环的内部合在一起形成一个大循环进行的!

在循环末尾加入对应的“把“-N”加入[测试列表]”(文件名:同步3)更加说明了这一点:

1
-1
2
-2
3
-3
1
-1
2
-2
3
-3
...

这时我们会发现一个更加有趣的现象:__一个循环的内部完成后,下一个循环的内部才会开始!__
也就是说,我们可以在循环的内部更加大胆地使用共用变量,因为 这个变量在循环里进行计算的时候,是不会被其他地方的积木影响的,也就是说,其他积木能够获得的,只有这个变量在一次循环之后的最终结果。

接下来来到了嵌套的循环,它会怎么表现呢?(文件名:同步4.sb3)

当点击绿旗时
重复执行
| 把 “1” 加入 [测试列表]
| 把 “-1 加入 [测试列表]
\------/

当点击绿旗时
重复执行
| 把 “2” 加入 [测试列表]
| 重复执行 10 次
| | 把 [变量1] 设为 平方根(变量1 + 1 / 变量1)
| \------------/
| 把 “-2” 加入 [测试列表]
\------/

结果(去掉部分换行方便阅读):

1 -1
2
1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1
(10个“1 -1”)
-2
1 -1
2
1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1
-2
...

为什么刚刚好有10个“-1 1”呢?难道是说和“重复执行10次”有关?……

把“重复执行 10 次”也进行处理后:(文件名:同步5.sb3)

当点击绿旗时
重复执行
| 把 “2” 加入 [测试列表]
| 重复执行 10 次
| | 把 “3” 加入 [测试列表]
| | 把 [变量1] 设为 平方根(变量1 + 1 / 变量1)
| | 把 “-3” 加入 [测试列表]
| \------------/
| 把 “-2” 加入 [测试列表]
\------/

结果:

1 -1 2
3 -3 1 -1 3 -3 1 -1 3 -3 1 -1 3 -3 1 -1 3 -3 1 -1
3 -3 1 -1 3 -3 1 -1 3 -3 1 -1 3 -3 1 -1 3 -3 1 -1
(10个“3 -3 1 -1”)
-2 1 -1 2
3 -3 1 -1 3 -3 1 -1 3 -3 1 -1 3 -3 1 -1 3 -3 1 -1
3 -3 1 -1 3 -3 1 -1 3 -3 1 -1 3 -3 1 -1 3 -3 1 -1
(10个“3 -3 1 -1”)
-2 1 -1 2
...

分析: 由于数字“1”代表的是最简单的循环(下称“简单循环”),我们不妨根据“1”循环进行分析,将每两个“1 -1”之间的循环定义为一个“循环周期”(这个技巧以后会经常用到)
同时给数字“2”和“3”代表的两个循环(下称“复杂循环”)的每个积木标上字母编号:

A 当点击绿旗时
B 重复执行
C | 把 “2” 加入 [测试列表]
D | 重复执行 10 次
E | | 把 “3” 加入 [测试列表]
F | | 把 [变量1] 设为 平方根(变量1 + 1 / 变量1)
G | | 把 “-3” 加入 [测试列表]
H | \------------/
I | 把 “-2” 加入 [测试列表]
J \------/

开始时的“1 -1 2 3 -3”表示在一个循环周期内,复杂循环从 A 运行到了 G,注意此时D处的重复执行已经执行了一次。接着简单循环就运行了。
然后是 9 个“1 -1 3 -3”,D处的重复执行(从 E 到 G)和简单循环交错进行。
此时D处的重复执行的次数已经到了。接下来的“1 -1 -2”,意味着复杂循环离开了“D循环”,从 H 出来到达 I。接着简单循环运行。
然后又是“1 -1 2 3 -3”,循环往复。

发现规律了吗?每一次简单循环都会在复杂循环运行到 G 和 I 的时候运行!而这些位置恰好是循环结束(H 和 J)的位置!
因此可以猜测:__当循环到达末尾的时候,会自动暂停,等待其他的循环运行,之后再开始下一个循环,或者运行后面的积木。__

在之后的内容,我们把类似 H、J 的位置叫做“休息点”,循环只能在“休息点”处暂停。

哪怕积木在不同的角色中,效果也是差不多的,除了顺序会有不同。(文件名:同步6.sb3)

接着再来看一看更加复杂的情况:(文件名:同步7.sb3)

我在这里面加入了各种循环积木。结论是:只有循环积木的末尾有休息点。“如果”积木不会产生休息点。

初步结论:
Scratch同时运行循环的办法:每一组积木都有自己的运行顺序,积木会按照运行顺序运行;
当遇到循环的末尾(“休息点”)时,积木暂停运行,按照顺序运行其他的积木,其他的积木也按照相同规则运行,直到再次轮到这个积木的时候,才继续运行。
这样就保证了Scratch里的循环能够保持“顺序一致”“速度一致”“互不干扰”,因此,在休息点之间运行的积木、设定的变量可以认为是“安全”的,不会穿插进行其他积木,受到其他积木的影响。
也就是说,如果你设定和读取变量之间不存在休息点,你不用担心类似于“设定的临时变量还没来得及使用就被另外一个循环的积木更改”的问题。

速度

之前提到过Scratch的循环有速度限制,但是前面的循环跑得飞快。这是怎么回事呢?
其实,如果你在某一个循环中放入一个“移动 10 步”积木,你就会发现他立即慢下来了,变成了一秒30次。
也就是说,当循环中存在运动、外观类或者其他会改变画面的积木时(例如“画笔”拓展),循环将被限速,且只要有一个运行着的循环中有这样的积木,所有的循环都会同时限速。可以使用“加速模式”解除限速。
“加速模式”只会解除限速,不会提高屏幕刷新率。所以屏幕仍然是30帧刷新一次。

有一些作品不使用“运行时不刷新屏幕”的功能,而是通过让用户开启加速模式来解除限速,再通过“等待”积木自行设定速度,其实这种方式并不好。

在有速度限制的时候,循环又会发生什么改变呢?(文件名:速度1.sb3)

当点击绿旗时
重复执行
| 把 连接“+1 ”和(计时器) 加入 [测试列表]
| 把 连接“-1 ”和(计时器) 加入 [测试列表]
\------/

当点击绿旗时
重复执行
| 把 连接“+2 ”和(计时器) 加入 [测试列表]
| 移动 1 步
| 把 连接“-2 ”和(计时器) 加入 [测试列表]
\------/

结果:

+1 0.011
-1 0.011
+2 0.011
-2 0.011
+1 0.044
-1 0.044
+2 0.044
-2 0.044
+1 0.078
-1 0.078
+2 0.078
-2 0.078

可以看到,每过一个“1 -1 2 -2”,时间就前进了0.033到0.034秒,恰好约等于三十分之一秒。
这个时候由于有了时间这一存在,我们可以转变为使用时间的改变作为基准来探究循环。
可以看到,“+1 -1 +2 -2”为一组,为什么一定是“+1 -1 +2 -2”而不是“+2 -2 +1 -1”呢?
这就要引出下面的话题:积木顺序。

打开加速模式后,和没有限速相同,这里不再演示。可以下载文件自行尝试。

顺序

继续打开上一次的作品。我发现如果只是单纯地把“移动 1 步”移到上面的积木中,或者把上面的积木换到下面,输出的效果不变。都是“1 -1 2 -2”。
但是如果把加入测试列表的“2”改成“1”,“1”改成“2”,顺序立马就变了,变成了“2 -2 1 -1”。
这说明这两个积木一定是有不同的,多次尝试后,我发现不同点在那个“当绿旗被点击”上。
当那两个“当绿旗被点击”交换位置后,顺序就变了。
这说明这个“当绿旗被点击”是会影响执行顺序的,我猜是按照从积木盒里面拖出的顺序决定,实验证明,应该没错。

右边的文件是我做的一个示例。绿旗的拖出顺序是1,4,5,3,2。(文件名:顺序1.sb3)

效果可以说是非常符合假设。

+1 0.003
-1 0.003
+4 0.003
-4 0.003
+5 0.003
-5 0.003
+3 0.003
-3 0.003
+2 0.003
-2 0.003
+1 0.036
-1 0.036
+4 0.036
-4 0.036
+5 0.036
-5 0.036
+3 0.036
-3 0.036
+2 0.036
-2 0.036
+1 0.069
-1 0.069
+4 0.069
...

经过一些实验,我又有了新的发现:(文件名:顺序2.sb3)
无论去掉绿旗还是保留绿旗,通过“点击”的方式启动循环的时候,循环的执行顺序会变成点击的顺序。
如果积木在不同角色里,则层叠顺序中前面的角色比后面的角色的积木先运行,背景最后运行

因此猜测:

  1. 积木的运行顺序就是他们被触发,也就是准备开始运行的顺序:哪个被触发的早,哪个优先级更高。
  2. 当绿旗被点击、按键被按下、角色被点击、事件被触发的时候,角色按照层叠顺序,从前到后开始触发,背景最后触发;相关的帽子积木按照在积木区里生成的顺序,从先到后开始触发。
  3. 看起来所有的相关事件积木同时开始,但是因为积木的触发有先后顺序,这些积木开始运行的时间也存在先后顺序,从而优先级有先后顺序。

克隆

在这次实验中,有两个角色,角色1会产生4个克隆体后执行循环,克隆体会通过“当作为克隆体启动”执行循环。角色2也会执行循环。点击背景时会发出一个广播并把计数器设为1,角色1和2接收广播,说出计数器的值并增加计数器,通过这种方式可以获得角色接收广播的顺序。(文件名:克隆.sb3)

可以看到,无论角色1在角色2的前面还是后面,角色1产生的克隆体都会在角色1的后面一层出现,越晚克隆的克隆体越在前面。

+1 0.027
-1 0.027
+2 0.027
-2 0.027
+11 0.027
-11 0.027
+12 0.027
-12 0.027
+13 0.027
-13 0.027
+14 0.027
-14 0.027
+1 0.06
-1 0.06
+2 0.06
-2 0.06
+11 0.06
-11 0.06
+12 0.06
-12 0.06
+13 0.06
-13 0.06
+14 0.06
-14 0.06

克隆体按照克隆的顺序决定“当作为克隆体启动”的运行顺序,但都在角色1、2的循环之后。

结论:角色接收广播的顺序就是角色的层叠顺序(包括克隆体)
克隆体克隆时将会插在本体的后面一层,由于克隆体的插入,原先在本体后面的角色都会后移一层。
“当作为克隆体启动”积木的启动时间是在克隆之后立即启动,没有时间差,不需要等待0.03秒,但是由于其他的“当绿旗被点击”积木已经被触发了,这一积木的启动顺序会被排在其他的“当绿旗被点击”积木之后。

广播

和上面的情况一样,广播作为触发类积木,当有广播被播报时,所有“当接收到对应的广播时”都会按照上面的顺序触发。因此可以使用广播来判断角色所在的图层。
广播和“当作为克隆体启动”类似,在广播发出之后将会在其他的积木之后触发。
如果在收到广播后创建克隆体,克隆体不会收到广播。
如果广播被打断,那么相当于所有的广播都被停止并重新触发。

我尝试了一些操作(文件名:广播1.sb3)
舞台有一按空格触发积木块,触发后会添加“!1”,发出广播;
积木块 1 是“简单循环”,积木块2、3有如下功能:
在广播开始的时候,添加“=2”或者“=3”
在广播后面循环的时候,添加“+2 -2”或者“+3 -3”

首先,在按下空格开始广播的时候,广播在这一回合接着所有积木之后开始:

...
+1 0.363
-1 0.363
+1 0.396 / 周期开始
-1 0.396
!1 0.396 < 这里开始了广播
=2 0.396 < 这里积木块 2 发生反应
+2 0.396
-2 0.396
=3 0.396 < 这里积木块 3 发生反应
+3 0.396
-3 0.396 \ 周期结束
+1 0.429
-1 0.429
+2 0.429
-2 0.429
+3 0.429
-3 0.429
...

之后,点击积木块 2,把它停止,再发出广播:

+1 1.255
-1 1.255
+3 1.255
-3 1.255
+1 1.287
-1 1.287
+3 1.287 < 这里积木块 3 还在运行
-3 1.287
!1 1.287 < 这里开始了广播
=2 1.287 < 这里积木块 2 发生反应
+2 1.287
-2 1.287 \ 周期结束
+1 1.321 / 周期开始
-1 1.321
=3 1.321 < 这里积木块 3 重新开始,但是保留了优先级
+3 1.321
-3 1.321
+2 1.321
-2 1.321
+1 1.353
-1 1.353
+3 1.353
-3 1.353
+2 1.353
-2 1.353

结论:当收到广播时,如果广播在运行,那么它会在下个回合重新开始。否则就会在这个回合立即开始。重新开始的广播保留原有的运行顺序。

等待

等待类积木(等待……,……并等待,在……秒内……),相当于“重复执行直到(等待结束的条件成立)”,这意味着等待类积木能够作为“休息点”,但是不能检测到其他积木的回合中的临时的变量变化,例如:(文件名:等待.sb3)

当点击绿旗时
重复执行
| 把[变量]设为 1
| 把[变量]设为 2 < 休息点在这
\------/

当点击绿旗时
等待 (变量) = 1

那个等待只能在它的运行时间判定,而在它的运行时间里,变量只可能等于2。

运行时不刷新屏幕

禁用里面的程序的所有休息点,这样子这些积木会在一个回合内执行。如果执行的时间太长(超过大约0.51秒),程序会在下一个休息点强行休息。(文件名:超时.sb3)

在 TurboWarp 中可以禁用循环计时器,也就是去掉半秒检查,使得程序运行更快。但是一旦发生死循环,TurboWarp 将会永远无法响应。

循环原理总结

**最后的猜想(在彻底了解原理之前一切只是假设)
Scratch 中有一个“运行队列” ,当积木被触发运行时,它会被加入到队列中;
Scratch 会一个“周期”、一个“周期”地运行“运行队列”中的积木。
在一个“周期”的开始,会先逐个按照队列运行每一个积木,我们把每一个积木的一次运行叫做一个“回合”。
在积木的一个“回合”内,
如果遇到“等待”类积木,检查等待是否结束。如果等待结束,则继续;否则,在此积木前暂停并退出此回合让其他积木共同运行(下一回合继续从等待积木开始);
如果遇到“重复执行”积木的末尾(“休息点”)并且没有“运行时不刷新屏幕”,或者这个回合时长超过半秒,则在此处暂停,退出此回合,让其他积木共同进行;
如果积木没有遇到上述情况,运行顺利结束,就会退出回合,从队列里删除;
如果运行期间遇到克隆,广播等事件,则与事件有关的积木会按照所属角色或者克隆体所在图层次序从前到后(背景最后),触发积木创建时间从早到晚的顺序,加到“运行队列”末尾,在这个周期里执行。
如果触发积木已经被加入到“运行队列”,则判定,如果是广播,则其在下一“周期”重新开始(不改变队列中的顺序),否则不加入。
“周期”在运行完队列里的积木(包括运行的时候新加到队列的积木)之后,检查屏幕是否在此“周期”内改变。如果改变,就检查这个回合所用的时间,如果小于三十分之一秒,就等待直到回合时间达到三十分之一秒。然后刷新屏幕,继续下一个“周期”。
如果积木被“停止”,它会被立即从队列里删除,如果在这个“周期”里还没被执行的积木因此被删除,则这些积木将不会被执行。换句话说,前面的积木可以通过“停止该角色中的其他脚本”打断该角色内等待运行的其他积木。**

附录7. 碰到颜色积木能接受的误差

“碰到颜色”积木并没有严格地判定是否确实碰到了这个颜色,它会接受一些误差不大的颜色。
在附录6的实验文件中还有一个“颜色.sb3”,它用来测试“碰到颜色”积木能容忍的颜色误差。
在 Scratch 中,__只要颜色的红、绿值除以8的商分别相等,且蓝值除以16的商相等__,他们就会被判定为同一种颜色。
例如rgb(3,15,276)和rgb(6,12,287)是同一种颜色,rgb(6,7,15)和rgb(8,8,16)不是同一种颜色。

附录8. 回答被打断的特殊情况

有的时候,当遇到需要“限时回答”或者需要创建“能关闭的回答”的时候,我会用一个角色来接受回答,然后让另一个角色广播并等待,第三个角色计时,这样可能会遇到这个问题:广播并等待的回答被打断没有特殊处理。
例如:
角色1:

当按下[空格]时
广播 [询问] 并等待
如果 (回答) = “delete” 那么
| 删除 [列表] 的全部项目
\-------------------------/

角色2:

当接收到[广播]时
询问 (确定要删除吗?(输入“delete”确定,10秒后自动取消)) 并等待
广播 [停止计时]

当接收到[时间到]时
停止[该角色的其他脚本]

角色3:

当接收到[广播]时
等待 10 秒
广播 [时间到]

当接收到[停止计时]时
停止[该角色的其他脚本]

这个积木看起来完全可行,但是有个隐患:
如果用户在第一次询问的时候确认了删除,在第二次询问的时候超过了时间,那么询问就会被打断。此时回答还保留着上一次的“delete”,所以这次就算超时未回答,列表也被清空了!
解决方法:询问开始之前,“将[回答完成]设为(0)”,询问完成之后,“将[回答完成]设为(1)”,删除之前同时判断(回答完成)=1和(回答)=“delete”。
最好的解决办法:不要分三个角色,把角色1,角色2合并为1个角色。这样“停止[该角色中的其他脚本]”会打断所有相关的积木。

附录9. 排查自己的程序卡在哪里

简单的方法:在每一个循环开始前加一个“将[测试变量]设为(序号)”,然后检查序号的值就知道卡在哪里了
复杂的方法:在每一个循环内部加入“添加(序号)到[测试列表]”,然后检查列表内容。此时列表内还可以顺便放入关键变量的值,方便调试。别忘了及时清空列表!

TurboWarp方法:

  1. 使用拓展“Debugger”代替“复杂的方法”
  2. 关闭编译模式,打开拓展“Running block border”,然后查看高亮的循环。

附录10. 把txt文件转换为csv文件的转换工具

复制粘贴以下代码进记事本保存为“转换器.js”,把需要处理的txt文件 需要是utf8编码 拖到 转换器.js 的图标上面,等待片刻后应该就会出现对应的csv文件。
不用担心Excel打开后中文乱码,Scratch是能够正常加载的。

SaveUTF8(
    arg(0).replace(/\.[^\.\\\/]*$/,".csv"),
    "\"" +
    LoadUTF8(arg(0))
    .replace(/"/g,"\"\"")
    .replace(/\r\n?|\n/g,"\"\r\n\"") + "\""
    );

function arg(n){
    return WSH.arguments(n);
}

function LoadUTF8(f){
    var sta = new ActiveXObject("Adodb.Stream");
    sta.type = 2;
    sta.mode = 3;
    sta.charset = "UTF-8";
    sta.open();
    sta.loadFromFile(f);
    var result = sta.readtext();
    sta.close();
    return result;
}

function SaveUTF8(f,str){
    var sta = new ActiveXObject("Adodb.Stream");
    sta.Type = 2;
    sta.mode = 3;
    sta.charset = "UTF-8";
    sta.open();
    sta.writetext(str);
    var stb = new ActiveXObject("Adodb.Stream");
    stb.Type = 1;
    stb.mode = 3;
    stb.open();
    sta.position = 3;
    sta.copyto(stb);
    stb.saveToFile(f,2);
    stb.close();
    sta.close();
}

voyage200
1 声望0 粉丝