漢諾塔(又稱河內(nèi)塔)游戲是來源于印度的一個(gè)古老傳說:大梵天創(chuàng)造世界的時(shí)候做了三根金剛石柱子,在一根柱子上從下往上按照大小順序摞著64片黃金圓盤。大梵天命令婆羅門把圓盤從下面開始按大小順序重新擺放在另一根柱子上。并且規(guī)定,在小圓盤上不能放大圓盤,在三根柱子之間一次只能移動(dòng)一個(gè)圓盤。
不論白天黑夜,總有一個(gè)僧侶在按照下面的規(guī)則移動(dòng)這些圓盤:一次只移動(dòng)一片,不管在哪根柱子上,小圓盤必須在大圓盤上面。僧侶們預(yù)言,當(dāng)所有的圓盤都從梵天放好的那根柱子上移到另外一根柱子上時(shí),世界就將在一聲霹靂中消滅,而梵塔、廟宇和眾生也都將同歸于盡(圖1)。
神話故事本身我們不需要深究,不過根據(jù)故事中的規(guī)則計(jì)算,若每秒移動(dòng)一次圓盤,完全移動(dòng)需要連續(xù)不斷地移動(dòng)5845.54億年以上,不管故事真假地球都早已毀滅了。那么如果是一個(gè)圓盤少一些的漢諾塔游戲,我們又需要移動(dòng)多久呢?這里我們嘗試按照傳說中的漢諾塔規(guī)則,編寫一個(gè)Scratch版本的漢諾塔游戲(圖2)。
首先我們需要總結(jié)漢諾塔的核心規(guī)則:有三根柱子可以放入圓盤,每個(gè)圓盤大小不同;最開始所有圓盤按照從小到大的順序放在第一根柱子上面,每根柱子上面的圓盤都只能小的在上面,大的在下面;每次只能移動(dòng)一個(gè)圓盤。
三根柱子可以用三個(gè)列表來記錄放入的圓盤;每個(gè)圓盤有獨(dú)立的編號(hào),編號(hào)需要和大小呈現(xiàn)正相關(guān),方便比較大小;每次移動(dòng)圓盤時(shí),可以將圓盤數(shù)據(jù)放入一個(gè)變量中,一次只能放入一個(gè)圓盤的數(shù)據(jù);放入圓盤時(shí),將提起的圓盤數(shù)據(jù)變量與放下的柱子列表最小項(xiàng)進(jìn)行比較,要小于列表最小項(xiàng)才可以放入列表。
游戲包含2個(gè)角色:向下箭頭、圓盤(用畫筆實(shí)時(shí)繪制);背景中繪制三根柱子。設(shè)定好各項(xiàng)變量:箭頭位置、提起、項(xiàng)數(shù)。設(shè)定好列表:一、二、三、高度位置。游戲開始后用畫筆工具按照變量列表值畫出需要的圓盤,之后可以控制箭頭選擇圓盤提起和放下,每次對(duì)圓盤產(chǎn)生操作,都要重新繪制所有圓盤。背景可以參考圖3自行繪制。
按照規(guī)則要求,我們需要三個(gè)柱子列表,這里取名“一、二、三”,另外需要確定圓盤的高度,游戲中我們只用五個(gè)圓盤,所以高度最多包含五項(xiàng),將對(duì)應(yīng)的圓盤y坐標(biāo)寫入“高度位置”列表中(寫一個(gè)文本,然后手動(dòng)導(dǎo)入到列表),第一個(gè)圓盤緊貼地面,之后每個(gè)圓盤之間的間隔距離為單個(gè)圓盤的高度,這里設(shè)為20。列表參考數(shù)值如圖,第一個(gè)圓盤的y坐標(biāo)以背景中基線為準(zhǔn)自行測量(圖4)。
將三個(gè)柱子列表清空后,將五個(gè)圓盤的寬度信息(項(xiàng)數(shù)×10)輸入第一個(gè)列表中,需要注意從大到小輸入,背景代碼參考如圖5。
圓盤使用畫筆實(shí)時(shí)繪制,畫筆角色不需要顯示出來,可以繪制一個(gè)小圓點(diǎn)造型(如圖6),將虛像調(diào)到最高讓它隱形。當(dāng)接收到廣播“畫出圓盤”時(shí),先清空之前的筆跡(圖7)。
然后開始繪制五個(gè)圓盤,圓盤位置由三個(gè)柱子列表提供x坐標(biāo)(三根柱子分別為-155,0,155),“高度位置”列表提供y坐標(biāo)。每個(gè)柱子需要繪制的圓盤個(gè)數(shù)由柱子列表的項(xiàng)數(shù)決定,需要注意的是:不同大小的圓盤,x坐標(biāo)的偏差值不一樣,列表能提供的x坐標(biāo)是中心點(diǎn)坐標(biāo),需要向左右偏移圓盤寬度的一半。同時(shí),為了讓圓盤與圓盤之間更容易區(qū)分,我們?yōu)槊總€(gè)圓盤設(shè)定不同的顏色,我們知道畫筆顏色的數(shù)值范圍是1-100,每個(gè)圓盤的大小差值為20,所以顏色可以設(shè)定為項(xiàng)數(shù)×6,在第一個(gè)柱子上繪制圓盤的程序如圖8。
接下來按照同樣的方法繪制出第二根和第三根柱子上的圓盤,x起始坐標(biāo)改為0和155(圖9)。
箭頭角色在造型中直接導(dǎo)入Scratch自帶素材(Arrow1-c)(圖10)。
通過左右鍵控制變量“箭頭位置”在1到3之間切換。按下右箭頭鍵,“箭頭位置”加1,按下左箭頭鍵則相反。當(dāng)“箭頭位置”等于1的時(shí)候,表示移到了第一根柱子上方,當(dāng)“箭頭位置”等于2的時(shí)候,移到第二根柱子上方,當(dāng)“箭頭位置”等于3的時(shí)候,移到第三根柱子上方。為了讓箭頭在3個(gè)位置間循環(huán),如果箭頭位置大于3時(shí),將箭頭位置設(shè)為1,或者小于1時(shí)將箭頭位置設(shè)為3(圖11)。
設(shè)置箭頭位置對(duì)應(yīng)的x坐標(biāo)(圖12)。
箭頭在提起和放入圓盤功能之間循環(huán),當(dāng)完成“提起圓盤”后,才可開始“放入圓盤”;完成“放入圓盤”后,才可以“提起圓盤”。每完成一段操作,則廣播畫出圓盤。每次廣播都需要等上一個(gè)廣播內(nèi)容完成,最開始還需要等待數(shù)據(jù)注入完成(圖13)。
接收到廣播“提起圓盤”后,為避免一次按鍵多次檢測,我們加上一個(gè)等待0.5秒,提示用戶按空格鍵提起圓盤。按下空格鍵后,還需保證當(dāng)前箭頭指向的柱子上存在圓盤,也就是對(duì)應(yīng)列表的項(xiàng)數(shù)大于0,才可以將最上面的圓盤保存到變量“提起”中,然后停止這個(gè)腳本(圖14)。
放入圓盤的方法與提起圓盤類似,不同之處在于按下空格鍵后,如果當(dāng)前箭頭指向的柱子沒有圓盤,也就是對(duì)應(yīng)列表項(xiàng)數(shù)為0,則直接將提起的圓盤數(shù)據(jù)放入對(duì)應(yīng)列表,并將變量“提起”設(shè)定為空,否則需要保證對(duì)應(yīng)列表最后一項(xiàng)比提起的圓盤更大,否則不能放入指定列表。放入成功后停止這個(gè)腳本(圖15)。
至此程序完成,測試完成無誤后,調(diào)整好變量列表的顯示與隱藏即可。我們通過對(duì)漢諾塔游戲規(guī)則的分拆解析,結(jié)合Scratch各模塊功能,創(chuàng)建以畫筆刷新屏幕改變顯示效果的機(jī)制,完成了Scratch版本的漢諾塔游戲。通過這個(gè)游戲我們可以掌握畫筆積木制作動(dòng)畫效果的方法、列表數(shù)據(jù)的提取和插入、變量儲(chǔ)存位置的方法、調(diào)取列表最后項(xiàng)的方法等知識(shí)點(diǎn)。
測試完成后,在背景代碼中添加調(diào)整變量和列表的顯示與隱藏(圖16)。
最后我們?cè)偎伎家幌?,如果需要加入更多的圓盤該修改哪些地方呢?除了舞臺(tái)背景中重復(fù)5次繪制的代碼肯定要改成6,“高度位置”列表中要添加一個(gè)新的高度值外,還有其他地方需要修改嗎(圖17)?
完成游戲后如何判斷游戲勝利并表示出來呢?可以添加一個(gè)表示勝利的背景(圖18)。那么你修改的程序和我的一樣嗎(圖19)?
想要記錄操作步數(shù),那么這個(gè)變量該怎么設(shè)置呢?27FDCB6F-FAC7-4B71-9829-B0BBAB7D1013