Python極客戰(zhàn)記關(guān)卡主要是偏向鍛煉用戶的基本語法結(jié)構(gòu)和計(jì)算機(jī)思維,讓大家熟悉極客戰(zhàn)記的操作與代碼的使用。來到了森林,關(guān)卡將會變得更多更難,同樣,到了森林,大家就正式開始接觸編程的幾大重要知識點(diǎn):條件判斷、運(yùn)算符、函數(shù)、對象屬性。
關(guān)卡簡介
事件處理函數(shù),看起來本關(guān)與它前面的幾關(guān)考查內(nèi)容相同,其實(shí)不然,如果忽略了事件處理函數(shù)的某個(gè)特點(diǎn),那你可能就無法通過本關(guān)了。其實(shí)大多數(shù)關(guān)卡需要填充的代碼并不多,大家如果完完全全按照注釋填寫,便可順利過關(guān),但如果不熟悉考查的知識點(diǎn),多數(shù)同學(xué)都會按自己的想法對注釋要求的代碼“畫蛇添足”,導(dǎo)致無法過關(guān),本關(guān)也是如此。
事件處理函數(shù)
先來了解一下事件處理函數(shù),我們初次接觸了這個(gè)知識點(diǎn):每個(gè)關(guān)卡的目標(biāo)頁和提示頁(圖1),都會包含對當(dāng)前關(guān)卡涉及的新知識點(diǎn)的講解,同學(xué)們每次都有認(rèn)真閱讀嗎?
函數(shù)大家已經(jīng)比較熟悉了,而事件(Events)卻是一個(gè)新的概念,什么是事件?當(dāng)你的英雄說話發(fā)出聲音時(shí),聽見聲音的人就是發(fā)生了聽見(hear)事件,當(dāng)你的英雄出現(xiàn)在游戲里時(shí),你的英雄就是發(fā)生了生成(spawn)事件。因此當(dāng)你的英雄做某事時(shí),則必然會有相應(yīng)的事件發(fā)生。
而事件處理函數(shù),可以看作一個(gè)監(jiān)測工具,或者說一個(gè)更高級的判斷代碼,時(shí)刻檢測著某事件,若發(fā)生了,則調(diào)用相應(yīng)的函數(shù)。因此,事件處理函數(shù)的使用格式為(圖2):pet.on(發(fā)生的事件名,調(diào)用的函數(shù))。這里有一個(gè)易錯(cuò)點(diǎn),要監(jiān)測的事件,我們要填寫的是事件的名字,也就是字符串,因此此處的事件名必須是包含在雙引號內(nèi)。
如果你到了這一關(guān)還不了解字符串的話,問題就比較嚴(yán)重了,可以點(diǎn)擊鏈接,了解字符串的相關(guān)知識。而要調(diào)用的函數(shù),我們直接把這個(gè)函數(shù)的函數(shù)名寫上去即可,不需要用雙引號包括。
可能到這里大家會有一個(gè)疑問,為什么事件名是一個(gè)字符串,而函數(shù)名不是字符串,不需要加雙引號呢?這是因?yàn)閯?chuàng)建一個(gè)函數(shù),實(shí)際上就是定義一個(gè)函數(shù):def 函數(shù)名,此時(shí)你的函數(shù)名就被關(guān)鍵字def進(jìn)行了定義,定義以后,這個(gè)函數(shù)名就不再是一個(gè)名字了,它變成了一個(gè)函數(shù),它代表的就是這個(gè)函數(shù),它成為了一個(gè)有定義的對象。
也就是說,雖然我們明白,這個(gè)單詞,它是這個(gè)函數(shù)的名字,但是電腦沒有名字這種概念,它只知道,這個(gè)單詞指的就是這個(gè)函數(shù)。即:函數(shù)名被定義以后,成為了一個(gè)對象,因此電腦就可以直接通過調(diào)用這個(gè)單詞來調(diào)用函數(shù)。因此函數(shù)的調(diào)用則不需要使用雙引號。
明白了事件函數(shù)的使用方法以后,我們再看看事件處理函數(shù)的特點(diǎn)。上方有提到,事件處理函數(shù)就像一個(gè)時(shí)刻監(jiān)測事件的機(jī)器,因此它一旦被運(yùn)行,被啟動了,就永遠(yuǎn)不會結(jié)束,會一直執(zhí)行它的任務(wù):監(jiān)測并調(diào)用相應(yīng)函數(shù)。這與普通的代碼是有區(qū)別的,大家都知道,正常的代碼,都是按自上而下的順序執(zhí)行,執(zhí)行完了,這一行代碼就結(jié)束了。因此我們的大部分通關(guān)代碼都是放在一個(gè)while-True無限循環(huán)內(nèi)的,為的就是利用循環(huán),讓我們的代碼無限運(yùn)行,不要一次性就結(jié)束了。
而事件處理函數(shù)則非常方便,這行代碼一旦被執(zhí)行,它的監(jiān)測工作就永遠(yuǎn)不會停止,也不會影響其他代碼的運(yùn)行,就像一個(gè)幫你做事的智能機(jī)器人,你可以做你自己的事,而一旦發(fā)生了事件,它就會盡職盡責(zé)地運(yùn)行需要運(yùn)行的函數(shù)。那么此時(shí)最大的變化即是:執(zhí)行代碼的人,從一個(gè)人(你的英雄),變成了兩個(gè)人(你的英雄和你的智能機(jī)器人),大大提高了代碼的效率,這就是多線程的思想。明白了事件處理函數(shù),我們就可以看看我們的關(guān)卡代碼了。
現(xiàn)在的你,應(yīng)該可以一眼就能看出當(dāng)前代碼的結(jié)構(gòu)了。4到7行(圖3),代碼定義了一個(gè)叫sayTwo的函數(shù),它和我們常見的函數(shù)有個(gè)區(qū)別,它自帶了一個(gè)叫做event的參數(shù),這個(gè)參數(shù)用于接收發(fā)生的事件,目前暫時(shí)沒有什么作用,屬于可有可無的存在。第9行,則是使用pet.on事件處理函數(shù),來監(jiān)測“hear”事件的發(fā)生,調(diào)用sayTwo函數(shù),那么此時(shí)通關(guān)思路為:編寫sayTwo函數(shù)與事件處理函數(shù)。
英雄說話提問
觸發(fā)事件處理函數(shù),調(diào)用sayTwo函數(shù)讓寵物回答。此時(shí),存在一個(gè)易錯(cuò)點(diǎn),有的同學(xué)認(rèn)為,英雄此時(shí)提了3個(gè)問題,所以寵物需要回答3次,所以他的代碼是這樣的:在sayTwo函數(shù)里讓寵物連續(xù)回答了3次答案(圖4)。
然后就會發(fā)現(xiàn)并不能過關(guān)。上文中有提到事件處理函數(shù)是一個(gè)時(shí)刻運(yùn)行永不停止的機(jī)器,也就是說無需在sayTwo函數(shù)里寫3次回答,游戲里每發(fā)生一次說話,寵物都能執(zhí)行一次回答,因此英雄提了3次問題,寵物就發(fā)生了3次hear事件,則相應(yīng)的,寵物會按順序執(zhí)行3次sayTwo函數(shù)。試想,如果你在sayTwo函數(shù)里,填寫了三句回答,那么此時(shí)你們的對話就變成了:
英雄:一加一等于幾?寵物:2,英雄:x^3 - 6x^2 + 12x - 8 = 0,x等于多少?寵物:2,英雄:火星有多少衛(wèi)星?寵物:2,寵物的每次回答都連續(xù)說了2,而正確答案其實(shí)就是2,僅有一個(gè),不能再多,所以無法過關(guān)。因此將多余的兩次回答刪去即可過關(guān)。通關(guān)代碼如圖5。