汉诺塔(又称河内塔)游戏是来源于印度的一个古老传说:大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
不论白天黑夜,总有一个僧侣在按照下面的规则移动这些圆盘:一次只移动一片,不管在哪根柱子上,小圆盘必须在大圆盘上面。僧侣们预言,当所有的圆盘都从梵天放好的那根柱子上移到另外一根柱子上时,世界就将在一声霹雳中消灭,而梵塔、庙宇和众生也都将同归于尽(图1)。
神话故事本身我们不需要深究,不过根据故事中的规则计算,若每秒移动一次圆盘,完全移动需要连续不断地移动5845.54亿年以上,不管故事真假地球都早已毁灭了。那么如果是一个圆盘少一些的汉诺塔游戏,我们又需要移动多久呢?这里我们尝试按照传说中的汉诺塔规则,编写一个Scratch版本的汉诺塔游戏(图2)。
首先我们需要总结汉诺塔的核心规则:有三根柱子可以放入圆盘,每个圆盘大小不同;最开始所有圆盘按照从小到大的顺序放在第一根柱子上面,每根柱子上面的圆盘都只能小的在上面,大的在下面;每次只能移动一个圆盘。
三根柱子可以用三个列表来记录放入的圆盘;每个圆盘有独立的编号,编号需要和大小呈現正相关,方便比较大小;每次移动圆盘时,可以将圆盘数据放入一个变量中,一次只能放入一个圆盘的数据;放入圆盘时,将提起的圆盘数据变量与放下的柱子列表最小项进行比较,要小于列表最小项才可以放入列表。
游戏包含2个角色:向下箭头、圆盘(用画笔实时绘制);背景中绘制三根柱子。设定好各项变量:箭头位置、提起、项数。设定好列表:一、二、三、高度位置。游戏开始后用画笔工具按照变量列表值画出需要的圆盘,之后可以控制箭头选择圆盘提起和放下,每次对圆盘产生操作,都要重新绘制所有圆盘。背景可以参考图3自行绘制。
按照规则要求,我们需要三个柱子列表,这里取名“一、二、三”,另外需要确定圆盘的高度,游戏中我们只用五个圆盘,所以高度最多包含五项,将对应的圆盘y坐标写入“高度位置”列表中(写一个文本,然后手动导入到列表),第一个圆盘紧贴地面,之后每个圆盘之间的间隔距离为单个圆盘的高度,这里设为20。列表参考数值如图,第一个圆盘的y坐标以背景中基线为准自行测量(图4)。
将三个柱子列表清空后,将五个圆盘的宽度信息(项数×10)输入第一个列表中,需要注意从大到小输入,背景代码参考如图5。
圆盘使用画笔实时绘制,画笔角色不需要显示出来,可以绘制一个小圆点造型(如图6),将虚像调到最高让它隐形。当接收到广播“画出圆盘”时,先清空之前的笔迹(图7)。
然后开始绘制五个圆盘,圆盘位置由三个柱子列表提供x坐标(三根柱子分别为-155,0,155),“高度位置”列表提供y坐标。每个柱子需要绘制的圆盘个数由柱子列表的项数决定,需要注意的是:不同大小的圆盘,x坐标的偏差值不一样,列表能提供的x坐标是中心点坐标,需要向左右偏移圆盘宽度的一半。同时,为了让圆盘与圆盘之间更容易区分,我们为每个圆盘设定不同的颜色,我们知道画笔颜色的数值范围是1-100,每个圆盘的大小差值为20,所以颜色可以设定为项数×6,在第一个柱子上绘制圆盘的程序如图8。
27FDCB6F-FAC7-4B71-9829-B0BBAB7D1013接下来按照同样的方法绘制出第二根和第三根柱子上的圆盘,x起始坐标改为0和155(图9)。
箭头角色在造型中直接导入Scratch自带素材(Arrow1-c)(图10)。
通过左右键控制变量“箭头位置”在1到3之间切换。按下右箭头键,“箭头位置”加1,按下左箭头键则相反。当“箭头位置”等于1的时候,表示移到了第一根柱子上方,当“箭头位置”等于2的时候,移到第二根柱子上方,当“箭头位置”等于3的时候,移到第三根柱子上方。为了让箭头在3个位置间循环,如果箭头位置大于3时,将箭头位置设为1,或者小于1时将箭头位置设为3(图11)。
设置箭头位置对应的x坐标(图12)。
箭头在提起和放入圆盘功能之间循环,当完成“提起圆盘”后,才可开始“放入圆盘”;完成“放入圆盘”后,才可以“提起圆盘”。每完成一段操作,则广播画出圆盘。每次广播都需要等上一个广播内容完成,最开始还需要等待数据注入完成(图13)。
接收到广播“提起圆盘”后,为避免一次按键多次检测,我们加上一个等待0.5秒,提示用户按空格键提起圆盘。按下空格键后,还需保证当前箭头指向的柱子上存在圆盘,也就是对应列表的项数大于0,才可以将最上面的圆盘保存到变量“提起”中,然后停止这个脚本(图14)。
放入圆盘的方法与提起圆盘类似,不同之处在于按下空格键后,如果当前箭头指向的柱子没有圆盘,也就是对应列表项数为0,则直接将提起的圆盘数据放入对应列表,并将变量“提起”设定为空,否则需要保证对应列表最后一项比提起的圆盘更大,否则不能放入指定列表。放入成功后停止这个脚本(图15)。
至此程序完成,测试完成无误后,调整好变量列表的显示与隐藏即可。我们通过对汉诺塔游戏规则的分拆解析,结合Scratch各模块功能,创建以画笔刷新屏幕改变显示效果的机制,完成了Scratch版本的汉诺塔游戏。通过这个游戏我们可以掌握画笔积木制作动画效果的方法、列表数据的提取和插入、变量储存位置的方法、调取列表最后项的方法等知识点。
测试完成后,在背景代码中添加调整变量和列表的显示与隐藏(图16)。
最后我们再思考一下,如果需要加入更多的圆盘该修改哪些地方呢?除了舞台背景中重复5次绘制的代码肯定要改成6,“高度位置”列表中要添加一个新的高度值外,还有其他地方需要修改吗(图17)?
完成游戏后如何判断游戏胜利并表示出来呢?可以添加一个表示胜利的背景(图18)。那么你修改的程序和我的一样吗(图19)?
想要记录操作步数,那么这个变量该怎么设置呢?27FDCB6F-FAC7-4B71-9829-B0BBAB7D1013