極客戰(zhàn)記的關(guān)卡主要是偏向鍛煉用戶(hù)的基本語(yǔ)法結(jié)構(gòu)和計(jì)算機(jī)思維,讓大家熟悉極客戰(zhàn)記的操作與代碼的使用。“似曾相似的味道”這關(guān)涉及的知識(shí)點(diǎn)較多,有字符串的連接,程序的自動(dòng)化邏輯,還有運(yùn)算符的使用,利用變量和字符串的連接,實(shí)現(xiàn)了循環(huán)自動(dòng)讓英雄唱歌的程序,合理利用變量和循環(huán),能讓你的程序更具備自動(dòng)性。
1. 思路講解
查看默認(rèn)代碼,在代碼里能看到一大段的英文,給人一種沒(méi)有翻譯完全的恐怖感,但實(shí)際上閱讀注釋就會(huì)知道,這一大段的英文,只是英雄需要唱的英文歌謠,我們不需要理解它的意思。
如果此時(shí)注釋閱讀完了,但仍不太清楚本關(guān)的任務(wù),還可以直接運(yùn)行游戲,看看默認(rèn)代碼的運(yùn)行情況及失敗原因。從左上角可以看到,本關(guān)的過(guò)關(guān)目標(biāo)是讓英雄跟著大家一起唱歌。
但是從實(shí)際的運(yùn)行情況來(lái)看,除了第一句“ 10 potions of health on the wall!”以外,英雄唱的都跟別人不一樣。因此我們可以按照注釋和游戲動(dòng)畫(huà)里的模板,為英雄添加代碼,讓英雄唱的內(nèi)容跟其他人一樣。從頭開(kāi)始查看動(dòng)畫(huà),觀察大塊頭的歌唱內(nèi)容:
10 potions of health on the wall!
10 potions of health!
Take 1 down, pass it around!
9 potions of health on the wall!
9 potions of health on the wall!
9 potions of health!
Take 1 down, pass it around!
8 potions of health on the wall!
8 potions of health on the wall!
……
可以看出歌唱的內(nèi)容似乎具有一定的重復(fù)性。再看看注釋給的歌唱模板。
如果把X當(dāng)成10,Y當(dāng)成1,就會(huì)發(fā)現(xiàn)這四句注釋的內(nèi)容恰好與前四句歌唱內(nèi)容一模一樣。然后再把X當(dāng)成9,Y當(dāng)成1,則又變成了接下來(lái)的四句。因此我們可以分析出,歌唱內(nèi)容具有一個(gè)循環(huán)性,每四句一個(gè)循環(huán),可以直接使用循環(huán)來(lái)讓英雄唱歌,減輕代碼量。但如果要使用循環(huán)又會(huì)有一個(gè)問(wèn)題,循環(huán)的內(nèi)容都是設(shè)定好的,但實(shí)際的歌唱內(nèi)容,每四句X就會(huì)減1,那么這個(gè)又該如何實(shí)現(xiàn)呢?
還記得在地牢里我們是怎么實(shí)現(xiàn)全自動(dòng)發(fā)現(xiàn)敵人攻擊敵人的嗎?
while True:
enemy = hero.findNearestEnemy()
if enemy:
hero.attack(enemy)
利用變量,我們隨時(shí)發(fā)現(xiàn)新的敵人,將它的名字賦入變量里,再讓英雄對(duì)這個(gè)變量發(fā)起進(jìn)攻,這樣就用一個(gè)變量,實(shí)現(xiàn)了發(fā)現(xiàn)敵人,攻擊敵人,再發(fā)現(xiàn)新敵人,再攻擊新敵人的程序邏輯。
因此,如果我們想要實(shí)現(xiàn)全自動(dòng)的循環(huán)唱歌,我們也可以利用變量。其實(shí)注釋里的模板就是給我們最大的提示,模板里的X和Y兩個(gè)未知數(shù),不正是我們需要設(shè)置變量的兩個(gè)內(nèi)容嗎?
前兩句唱的是X,第三句唱Y,而第四句就是唱X-Y,唱完四句,再讓X變量減1,Y不變,開(kāi)始下一個(gè)循環(huán)。明白了過(guò)關(guān)思路后,那么我們就可以開(kāi)始動(dòng)手寫(xiě)代碼了。此時(shí)或許會(huì)有一個(gè)問(wèn)題,變量如何和字符串混用?
2.字符串連接
以往我們說(shuō)話,輸出字符串,有兩個(gè)方式:(1)直接輸出型;(2)變量間接輸出型。從來(lái)沒(méi)有試過(guò)變量和字符串同時(shí)混用的,你不能把變量加到雙引號(hào)內(nèi),這樣它就變成了一個(gè)普通的字符,也不能放在雙引號(hào)外,直接混用會(huì)發(fā)生報(bào)錯(cuò)。
此時(shí)我們就需要使用加號(hào)連接符「+」,當(dāng)我們需要將變量和字符串同時(shí)輸出的時(shí)候,我們就需要將加號(hào)連接符「+」放在兩個(gè)內(nèi)容的中間,就像這樣:
此時(shí)報(bào)錯(cuò)就解除了,英雄也能準(zhǔn)確說(shuō)出要說(shuō)的內(nèi)容。明白了使用方法后,即可開(kāi)始編寫(xiě)過(guò)關(guān)代碼。系統(tǒng)已為我們定義好兩個(gè)變量,根據(jù)第11行的歌唱內(nèi)容,我們也能分析出potionsOnTheWall對(duì)應(yīng)的正是X,numToTakeDown對(duì)應(yīng)的是Y。因此我們可以補(bǔ)出后面的代碼:
連接的時(shí)候,可千萬(wàn)別忘了用于美觀的空格。寫(xiě)到第16行的時(shí)候,你看到了一行陌生的代碼,如果你不知道它的作用,可以先將它刪去,然后按照自己的思路進(jìn)行過(guò)關(guān),一會(huì)兒我們?cè)賹?duì)這行代碼進(jìn)行講解。寫(xiě)上最后一句,這時(shí),循環(huán)的前四句要歌唱的內(nèi)容已經(jīng)寫(xiě)好,接下來(lái)如果要進(jìn)入下一句循環(huán),我們需要將X,也就是potionsOnTheWall減1。這樣,我們就可以順利通關(guān)了。
但這還并不是完美的通關(guān)代碼,根據(jù)歌謠的內(nèi)容,其實(shí)每一次X減去的數(shù)值都是Y的數(shù)值,而Y剛好是1,因此我們最后一行就可以直接寫(xiě)X - 1,但這仍然并不完美,因?yàn)槿绻鸜的數(shù)值改變了,那么我們還要手動(dòng)更改最后一行的數(shù)值,所以我們還可以對(duì)代碼做一定的修改。
3.自增自減運(yùn)算
看到最后一行代碼,我們?cè)谶@一行里,進(jìn)行了一個(gè)減法的運(yùn)算,讓potionsOnTheWall的值等于potionsOnTheWall - 1,這就是一個(gè)自減的運(yùn)算。
比如potionsOnTheWall = potionsOnTheWall - 1,因?yàn)樵诖a中,像加減乘除這一類(lèi)運(yùn)算式是優(yōu)先計(jì)算的,所以這一行的代碼,會(huì)先執(zhí)行potionsOnTheWall - 1 ,然后得出結(jié)果,當(dāng)potionsOnTheWall為10時(shí),這里的結(jié)果就會(huì)是9。
然后再執(zhí)行賦值運(yùn)算「=」,用等號(hào),將結(jié)果賦入potionsOnTheWall變量中,這樣就實(shí)現(xiàn)了potionsOnTheWall變量的自我減少。由于1和變量numToTakeDown的值是一樣的,為了實(shí)現(xiàn)更方便的代碼,讓每次potionsOnTheWall都減去的是numToTakeDown的值而不是我們手動(dòng)設(shè)定的值,我們可以把此處的1,替換成numToTakeDown。
就像這樣,效果也是一樣的,而這種自減運(yùn)算,還有一種縮寫(xiě)形式:直接把減號(hào)、等號(hào),還有重復(fù)的內(nèi)容省去,這也就是我們剛剛刪除掉的代碼了。它的作用,就是將potionsOnTheWall自減去numToTakeDown的值,同理也還有自增語(yǔ)句。因此我們可以對(duì)代碼結(jié)構(gòu)優(yōu)化一下,在最后一句歌詞前,先進(jìn)行一次自減,然后potionsOnTheWall的值就減少了1,就可以直接在最后一句歌詞里使用potionsOnTheWall變量了。此時(shí)的代碼,就更為靈活精簡(jiǎn)了。