什么是馬里奧醒陆?一個(gè)裝著 16 × 32 個(gè)小色塊的長(zhǎng)方形,其中一些色塊填著顏色裆针,另一些沒有刨摩。什么是花寺晌?一個(gè) 16 × 16 的正方形。什么是「變身」澡刹?把馬里奧這個(gè)方塊里面代表衣服的褐色變成紅色呻征,代表背帶褲的紅色變成白色。什么是褐色罢浇?暫且說它是 0x887000 這個(gè)數(shù)字陆赋。什么是「碰到」?馬里奧的長(zhǎng)方形與花朵的正方形有所重疊嚷闭。什么是「重疊」攒岛?假設(shè)馬里奧的這個(gè)方塊占據(jù)屏幕(什么是屏幕?一個(gè)能裝下 256 × 240 個(gè)小色塊的矩形)中 X 方向 101 到 116胞锰、Y 方向 21 到 52 之間的區(qū)域灾锯,那么只要這個(gè)區(qū)域內(nèi)有一點(diǎn)或更多點(diǎn)也被花朵所占據(jù)(比如花朵處在 X 116 到 131、Y 21 到 36 之間的區(qū)域內(nèi))嗅榕,我們就認(rèn)為兩者有所重疊顺饮。
若給定以八個(gè)數(shù)值代表的兩個(gè)矩形區(qū)域,請(qǐng)寫出判斷兩個(gè)區(qū)域是否有重疊的 C 語(yǔ)言程序凌那。如果你能寫出來(lái)领突,那么祝賀你,如果有朝一日你想自己用 C 做一遍 NES 版本的《超級(jí)馬里奧》案怯,你至少知道讓他變身需要做什么了君旦。
是的,C 語(yǔ)言也許「只能」做數(shù)學(xué)題嘲碱〗鹂常可是,絕大多數(shù)游戲的運(yùn)行過程就是不停地做數(shù)學(xué)題麦锯,而所謂編寫游戲恕稠,也就是把游戲的規(guī)則和游戲的效果轉(zhuǎn)化為數(shù)學(xué)題而已。其中不少題目電腦都已經(jīng)知道怎么解——是別的程序員事先告訴它的——比如「求一堆散落在三維直角座標(biāo)系之中的多面體在 8(x?3)?10(y+1)?11(z?1)=0 這個(gè)平面上一個(gè)給定范圍內(nèi)的投影」或者「給定一些彼此相連的頂點(diǎn)扶欣,求任意兩點(diǎn)之間的最短路徑」之類的數(shù)學(xué)題鹅巍,它只需要千萬(wàn)分之一秒就能給你解好。這種能力有什么用料祠?電腦上 FPS 游戲的本質(zhì)活動(dòng)就是不停地求三維座標(biāo)系下的多面體經(jīng)過變換之后在二維平面上的投影骆捧,不停地判斷兩個(gè)多面體是否彼此重疊,以及不停地尋找兩個(gè)頂點(diǎn)之間的最短路徑髓绽,最終達(dá)到讓怪物沖到你面前咬你一口的目的敛苇。不止游戲如此,其他軟件也都差不多顺呕,每一個(gè)細(xì)節(jié)都是某種數(shù)學(xué)題——比如知乎頁(yè)面頂端的藍(lán)色導(dǎo)航條背景枫攀,就是 CSS 描述的一個(gè)淺藍(lán)到深藍(lán)的漸變——漸變是怎么回事呢括饶?給出兩個(gè)數(shù)字分別代表兩種顏色,以及第三個(gè)數(shù)字代表一段距離来涨,求一系列顏色的數(shù)值以及次序图焰,使得這段距離中兩種相鄰顏色之間的變化最小。數(shù)學(xué)題蹦掐。別說 C 語(yǔ)言楞泼,一切編程語(yǔ)言最終都只能做數(shù)學(xué)題,根據(jù)給定的數(shù)據(jù)笤闯,算出另一些數(shù)據(jù)堕阔,算出更多的數(shù)據(jù),然后存貯颗味、發(fā)送或者呈現(xiàn)算出的數(shù)據(jù)超陆。
不過我能理解你的困惑。投入大量時(shí)間看完教程浦马,結(jié)果只能在黑框里輸出一串?dāng)?shù)字时呀。這是在學(xué)編程還是在向七十年代致敬?編程是這樣無(wú)法給人成就感的活動(dòng)嗎晶默?是谨娜,也不是』嵌福看你的表述趴梢,應(yīng)該不是小孩子了,因?yàn)樾『⒆硬粫?huì)因?yàn)槌鯇W(xué)編程能做的事情很少而沒有成就感币他,或者說坞靶,覺得這樣做沒有成就感的小孩子根本不會(huì)繼續(xù)學(xué)下去。最初學(xué)編程的成就感單純來(lái)自于「我居然可以指揮機(jī)器做一些事」蝴悉,至少我小時(shí)候用中華學(xué)習(xí)機(jī)編一個(gè)程序幫我算暑假作業(yè)上的四則運(yùn)算題時(shí)是這樣感覺的彰阴。寫出這些程序并用它解題雖然遠(yuǎn)比自己動(dòng)筆去把題目算出來(lái)費(fèi)時(shí),卻讓人樂此不疲拍冠。那時(shí)候我還不知道馬里奧碰到花會(huì)變身這種事情其實(shí)也是靠編程編出來(lái)尿这,所以我也不會(huì)去想學(xué)編程「并不能做什么」。
無(wú)奈大多數(shù)人過了一定年紀(jì)就很難再靠「我能指揮機(jī)器」這種簡(jiǎn)單原始的快樂來(lái)驅(qū)動(dòng)自己學(xué)編程庆杜。見過世面射众,聽過傳言,欲望和野心變得復(fù)雜而龐大欣福,你想要圖形界面责球,音樂音效焦履,人工智能拓劝,云端同步雏逾,可是你悶頭學(xué)了幾堂課,還是只學(xué)會(huì)在黑框里顯示一串?dāng)?shù)字郑临。你懷疑這是學(xué) C 語(yǔ)言的錯(cuò)栖博,于是你到知乎上來(lái)問了這個(gè)問題。
你的疑惑是有道理的厢洞。
如果能把編程學(xué)下去仇让,日后你就會(huì)明白,任何程序都是一座冰山躺翻,最終用戶能看到的界面和使用的功能丧叽,只是程序浮在水面上的十分之一。知乎這個(gè)網(wǎng)站其實(shí)也是個(gè)運(yùn)行在某臺(tái)電腦上的程序公你,你能看到的十分之一是用什么編寫的呢踊淳?HTML,CSS陕靠,JavaScript迂尝,或者 Objective-C。而你看不到的那十分之九是用什么編寫的呢剪芥?Python垄开。這些你無(wú)法直接觀測(cè)到的 Python 程序運(yùn)行在世界某個(gè)角落的某些計(jì)算機(jī)上,隔著光纜税肪、雙絞線和無(wú)線基站溉躲,為你面前或掌上的用戶界面注入生命。
( xkcd: Python )
……可是 Python 是用什么編寫的呢益兄?C 語(yǔ)言(當(dāng)然签财,這么說并不嚴(yán)謹(jǐn),Python 理論上可以用任何其他語(yǔ)言實(shí)現(xiàn)偏塞,實(shí)際上也已經(jīng)被用很多其他語(yǔ)言實(shí)現(xiàn)了唱蒸,不過這并不是重點(diǎn))。任何編程語(yǔ)言都是實(shí)現(xiàn)某個(gè)功能的工具灸叼,Python 實(shí)現(xiàn)了知乎這個(gè)網(wǎng)站的大部分功能神汹,而 C 實(shí)現(xiàn)了「用 Python 寫程序」這個(gè)功能。為什么是 C古今?
C 很別扭又缺陷重重屁魏,卻異常成功。固然有歷史的巧合推波助瀾捉腥,可也的確是因?yàn)樗軡M足對(duì)于這樣一種系統(tǒng)實(shí)現(xiàn)語(yǔ)言的需要:既有相當(dāng)?shù)男蕘?lái)取代匯編語(yǔ)言氓拼,且又足夠地抽象而流暢,能夠用于描述各種各樣的環(huán)境之下的算法與交互。
C is quirky, flawed, and an enormous success. Although accidents of history surely helped, it evidently satisfied a need for a system implementation language efficient enough to displace assembly language, yet sufficiently abstract and fluent to describe algorithms and interactions in a wide variety of environments.
——C 語(yǔ)言之父桃漾,Dennis M. Ritchie
C 是初代程序員所使用的語(yǔ)言坏匪,那時(shí)候硬件很貴,軟件必須高效撬统;而計(jì)算機(jī)的用戶都是職業(yè)程序員适滓,對(duì)于硬件有足夠的理解。C 貼近硬件恋追,就意味著它容易譯成機(jī)器能懂的語(yǔ)言凭迹,而它的設(shè)計(jì)者也并不需要操心普通人學(xué)起來(lái)可能會(huì)比較困難——而且,說真的苦囱,其實(shí)也不很難嗅绸。但是,這么多年過去之后撕彤,軟件規(guī)模變得越來(lái)越大朽砰,C 就像錘子和手鋸,修小木屋得心應(yīng)手喉刘,造摩天樓就比較力不從心瞧柔;但 C 語(yǔ)言可以用來(lái)造出其他更適合建造摩天樓的工具,乃至組成摩天樓的預(yù)制件睦裳,就好比用錘子和手鋸造出挖掘機(jī)和吊車造锅、混凝土板和一體門窗一樣(當(dāng)然,這個(gè)類比并不十分貼切廉邑「缥担可是沒有什么類比能貼切地描述軟件工程,因?yàn)檐浖こ滔裨S多東西蛛蒙,卻又什么東西都不像)糙箍。
所以,回到你的問題上來(lái)牵祟,是的深夯,學(xué)會(huì) C 計(jì)算機(jī)語(yǔ)言真的可以開發(fā)出很多東西,但除非內(nèi)力深厚诺苹,場(chǎng)合適當(dāng)咕晋,并且閑得蛋疼,大多數(shù)人不會(huì)拿 C 或者只拿 C 來(lái)開發(fā)太大的東西收奔。如果你只是想要一門能夠讓你「編輯出一個(gè)啥子游戲或者軟件出來(lái)」的語(yǔ)言掌呜,而且你用 Windows,那建議你轉(zhuǎn)去學(xué)學(xué) C#坪哄。它長(zhǎng)得和 C 挺像质蕉,但卻能迅速地寫出至少是帶有圖形界面的程序势篡,用起來(lái)也很方便,鼠標(biāo)點(diǎn)一點(diǎn)就能讓你對(duì)自己的程序看起來(lái)什么樣有個(gè)比較直觀的印象模暗。還有禁悠,在國(guó)內(nèi),C# 的教材也相當(dāng)容易找到汰蓉。當(dāng)然 Python 也是一個(gè)很好的選擇绷蹲。
另外棒卷,還有一件事你必須弄明白:現(xiàn)代的所謂編程這一活動(dòng)顾孽,其實(shí)大部分時(shí)候是在「合理地堆砌別人已經(jīng)實(shí)現(xiàn)的功能來(lái)實(shí)現(xiàn)新的功能」,C 語(yǔ)言莫不如是比规,比如 printf 這個(gè)東西,是別人做出來(lái)的「把一些數(shù)據(jù)按照指定格式輸出到屏幕上」這一功能蜒什。而別人還做出來(lái)許多其他功能测秸,比如「在發(fā)現(xiàn)用戶短時(shí)間內(nèi)連續(xù)兩次按下鼠標(biāo)又松開的時(shí)候調(diào)用你寫好的一個(gè)函數(shù)」。學(xué)會(huì)怎樣在 C 或者其他任何程序語(yǔ)言中使用這些既有功能灾常,也是學(xué)習(xí)編程的一門重頭戲霎冯。等你弄明白這一點(diǎn),你也就找到了你問題的答案钞瀑。
有問題或者想獲取學(xué)習(xí)資料歡迎加我的群639368839