資訊內(nèi)容
控制Scratch異步代碼的執(zhí)行順序
你是否在編寫項目時遇到過一些棘手的BUG,比如邏輯明明是通順的,但是執(zhí)行結(jié)果卻不符預(yù)期。又如兩段代碼完完全全一模一樣,但是結(jié)果卻大相徑庭。這極有可能是代碼的執(zhí)行順序沒有得到控制所導(dǎo)致的,這是一些初學(xué)者常常會遇到的問題。本文將分析這種代碼執(zhí)行順序失控的原因及其應(yīng)對方法。
01
依照慣例,先來看幾個案例。
《恐龍吃蘋果》
舞臺布局
恐龍代碼
使用鍵盤方向鍵控制恐龍移動,點擊綠旗使恐龍回到起始位置,準(zhǔn)備進行下一次游戲。
蘋果代碼
判斷蘋果是否碰到恐龍,一旦碰到則隱藏,當(dāng)綠旗被點擊時將蘋果切換至顯示狀態(tài),準(zhǔn)備進行下一次游戲。
案例很普通,代碼也普通得不能再普通了,都進行了初始化操作,甚至可以說代碼是比較規(guī)范的。那么來看一下實際運行效果。
案例效果
注意到問題所在了嗎?在圖中,一共點擊了三次綠旗,第一次,啟動程序,控制恐龍移動,蘋果被恐龍吃掉-隱藏;第二次點擊綠旗,重啟程序,恐龍確實回到初始位置了,但是,明明設(shè)置了顯示狀態(tài)的初始化,蘋果卻并沒有出現(xiàn)。第三次點擊綠旗才出現(xiàn)。
問題是,為什么第二次點擊綠旗時,蘋果沒有按照預(yù)想的那樣,切換成顯示狀態(tài)呢?
在Scratch中遇到BUG時,有很多種調(diào)試方法,這次介紹一種變量法,通過變量來判斷某處代碼是否執(zhí)行、執(zhí)行次數(shù)。
新建變量“score”,在蘋果代碼中增加【將(score)增加(1)】
為了調(diào)試BUG,因此在這里不對變量做初始化。
調(diào)試效果
變量score初始值為0,在第一次點擊綠旗,被恐龍吃掉后,score的值變?yōu)?,此時再次點擊綠旗重啟程序,恐龍回到初始位置,蘋果沒有顯示,而score的值此時變?yōu)?,說明畫圈處的代碼被執(zhí)行了兩次。
所以,蘋果并不是沒有顯示,而是顯示后再一次碰到恐龍,再次隱藏。唯一合理的解釋是,在第二次點擊綠旗時,蘋果的代碼被先執(zhí)行了,而此時恐龍并沒有回到初始位置,因此蘋果再次碰到恐龍,再次隱藏。這時候再執(zhí)行恐龍的代碼,恐龍回到初始位置,為時已晚,蘋果已經(jīng)被恐龍“誤食”了。
在Scratch中,看似同時執(zhí)行的代碼,實則是有先后順序的。兩段代碼沒有按照預(yù)想的先后順序執(zhí)行,導(dǎo)致程序初始化時出現(xiàn)BUG。
很多初學(xué)者經(jīng)常會遇到這樣的問題,有的程序點擊一次是無法正常運行的,第二次點擊才會正常。大多數(shù)情況其實和上文中展示的這個案例屬于同一種情況。如果再次遇到類似這樣的情況,就要好好考慮一下是不是由于沒有控制好代碼的先后執(zhí)行順序而導(dǎo)致初始化BUG。
02
這個問題應(yīng)該如何解決呢?既然是代碼執(zhí)行順序不受控制,那么最簡單的方法就是通過【等待()秒】積木來調(diào)整順序。我們希望的是恐龍先“離開事發(fā)地點”,回到初始位置,再執(zhí)行蘋果是否碰到恐龍的代碼,只需要在點擊綠旗后,等待一段短暫的時間再執(zhí)行這段代碼即可。
至于等待的時間,設(shè)置成0.1還是0.01其實都可以,但是在這里我建議將數(shù)值設(shè)為0,即【等待(0)秒】。兩段當(dāng)綠旗被點擊積木下的代碼的先后執(zhí)行順序間隔非常短,等待0秒積木足以改變其順序。因為【等待()秒】積木會刷新屏幕,而刷新屏幕相對來說耗時較長(參見淺談Scratch的舞臺刷新機制 Part 2——在常規(guī)積木中的應(yīng)用)。
加入【等待(0)秒】后,蘋果初始化正常
這在我看來有兩點意義,一是副作用最小,我們的目的是控制程序運行的先后順序,但是如果等待的時間過久,會造成明顯的卡頓,因此在能保證代碼運行順序的前提下,時間越短越好。二是起到一種標(biāo)志作用,這種特殊的用法我們不妨約定俗成地將其視作為解決這類BUG的標(biāo)志,一旦看到這樣的用法,就知道是用來控制代碼執(zhí)行順序的。
關(guān)于【等待(0)秒】還可以參照科技傳播坊的疑難雜癥視頻 vol.41 《等待0秒的意義》。
03
BUG是解決了,但是在《恐龍吃蘋果》這個案例中,為什么是先執(zhí)行蘋果的代碼再執(zhí)行恐龍的代碼?而不是反過來呢?是什么決定了代碼的執(zhí)行順序?
為了更直觀地表現(xiàn)代碼的執(zhí)行順序,我們換一個更簡單的案例,通過變量來展現(xiàn)執(zhí)行順序。
圖層順序?qū)τ诋惒酱a執(zhí)行順序的影響
初始狀態(tài)下,橘貓的代碼是將變量設(shè)為0,圖層在后,藍貓的代碼是將變量設(shè)置為1,圖層在前。運行結(jié)果為0,表明藍貓的代碼先執(zhí)行了,橘貓后執(zhí)行,將變量覆蓋為0。
通過鼠標(biāo)拖拽改變圖層順序,將橘貓圖層置于藍貓前面。運行結(jié)果為1,表明橘貓的代碼先執(zhí)行了,藍貓后執(zhí)行,將變量覆蓋為1。
通過實驗我們可以得出以下結(jié)論:
不同角色的異步代碼執(zhí)行順序如下:角色圖層在前的先執(zhí)行,圖層在后的后執(zhí)行,此規(guī)則亦適用于舞臺,其圖層永遠在最后層。
為排除鼠標(biāo)拖拽可能產(chǎn)生的其他因素,通過代碼調(diào)整圖層順序,結(jié)論依舊成立。
04
盡管調(diào)整圖層順序是一種可控的、確定的能控制異步代碼執(zhí)行順序的方法,但是編寫程序的我們不可能通過手動拖拽角色來控制代碼執(zhí)行順序。萬一體驗者在非全屏模式下不小心拖拽了某個角色,改變了執(zhí)行順序而導(dǎo)致BUG。代碼明明完全一樣,但就是無法正常運行,那將會是一件多么尷尬的事。(下次再遇到這樣的情況可以考慮一下是否是因為圖層順序影響了代碼執(zhí)行順序,而又沒有很好地控制執(zhí)行順序)
為控制代碼執(zhí)行順序,上文中也提到了,可以使用【等待(0)秒】積木來解決,這種方法簡單直接,且對原代碼的改動最小,建議新手使用。
但是這是一種“把代碼寫死”的做法,在此給追求優(yōu)質(zhì)代碼的scratchers提供一種更完美的思路——消息,利用消息來控制代碼的執(zhí)行順序。
橘貓代碼
藍貓代碼
通過【廣播()并等待】實現(xiàn)同步
隨手畫的流程圖
控制代碼的執(zhí)行順序,你學(xué)會了嗎?
聲明:本文章由網(wǎng)友投稿作為教育分享用途,如有侵權(quán)原作者可通過郵件及時和我們聯(lián)系刪除
