每个程序员都应该挑战的6个项目
作者:Austin Z. Henley
編譯:碼農(nóng)翻身?
有不少學(xué)生和專(zhuān)業(yè)的開(kāi)發(fā)人員都想做一個(gè)業(yè)余的項(xiàng)目,以此來(lái)鍛煉提高自己的技術(shù)能力,但是他們并不清楚要做點(diǎn)啥。
我給大家看下這幾個(gè)讓我受益匪淺的項(xiàng)目,每個(gè)項(xiàng)目都可以多做幾次,每次都會(huì)讓你學(xué)到新的東西。當(dāng)你不知道學(xué)習(xí)什么東西的時(shí)候,不妨以這些項(xiàng)目作為驅(qū)動(dòng)。
文本編輯器
我們每天都使用文本編輯器,但是你知道他們到底是怎么工作的嗎?忽略掉那些炫酷的功能,你怎么實(shí)現(xiàn)一個(gè)能夠支持選擇,插入,刪除文本,并且移動(dòng)光標(biāo)的文本框呢??
當(dāng)然了,你不能使用那些GUI框架中已經(jīng)做好的文本框組件。?
最大的挑戰(zhàn)就是弄清楚如何在內(nèi)存中保存文檔,我首先想到的就是數(shù)組,可是數(shù)組在插入文本的時(shí)候有著很差勁的性能。幸運(yùn)的是,還有幾個(gè)漂亮的數(shù)據(jù)結(jié)構(gòu)來(lái)解決這個(gè)問(wèn)題。?
另外一個(gè)難點(diǎn)就是理解光標(biāo)在文本編輯器中的行為,比如,當(dāng)我在一個(gè)文本的中央,開(kāi)始按“向上”箭頭的時(shí)候,光標(biāo)應(yīng)該向哪里移動(dòng)??
在同一列移動(dòng)?不,如果上面的那一行比較短,光標(biāo)會(huì)移動(dòng)到那一行的末尾,然后再往上移動(dòng),如果那一行文本較長(zhǎng),光標(biāo)還會(huì)回到那一行的中間位置。
這就意味著需要記住光標(biāo)所在的列,這樣才有可能回來(lái)。我之前根本沒(méi)有注意到這些小細(xì)節(jié),直到我開(kāi)始實(shí)現(xiàn)的時(shí)候。?
實(shí)現(xiàn)了基本的編輯功能以后,下面兩個(gè)更有趣的挑戰(zhàn)是:undo/redo和單詞換行。?
以有效的方式來(lái)實(shí)現(xiàn)undo/redo讓我大吃一驚,我先是嘗試了用一個(gè)數(shù)組保持之前的狀態(tài),然后轉(zhuǎn)向了Memento 模式,最后才使用了命令模式。?而單詞換行會(huì)強(qiáng)迫你把文本的內(nèi)存存儲(chǔ)和視覺(jué)表現(xiàn)分開(kāi)。?
從文本編輯器能學(xué)到的東西?
-
存儲(chǔ)文本的數(shù)據(jù)結(jié)構(gòu):array, rope, gap buffer, piece table.
-
光標(biāo)的行為和實(shí)現(xiàn)?
-
undo/redo的設(shè)計(jì)模式?
-
利用抽象把文本的存儲(chǔ)和表現(xiàn)分開(kāi)??
進(jìn)一步閱讀:?
文本編輯器的數(shù)據(jù)結(jié)構(gòu):
https://www.averylaird.com/programming/the%20text%20editor/2017/09/30/the-piece-table/?
設(shè)計(jì)和實(shí)現(xiàn)一個(gè)Win32的文本編輯器:?
http://www.catch22.net/tuts/neatpad#?
《數(shù)據(jù)結(jié)構(gòu)和算法:Java描述》 ?
(碼農(nóng)翻身老劉亂入:我更推薦《算法》)?
2D 游戲 -- 太空入侵者 ?
即使是最簡(jiǎn)單的游戲也需要獨(dú)特的數(shù)據(jù)結(jié)構(gòu)和設(shè)計(jì)模式,我們是來(lái)學(xué)習(xí)的,所以最好使用一個(gè)簡(jiǎn)單的2D圖形庫(kù)(如SDL,SFML,PyGame),而不是一個(gè)隱藏了很多細(xì)節(jié)的大型游戲引擎。?
首先,你得學(xué)會(huì)如何在屏幕上繪制東西,實(shí)際上你是在清理屏幕,然后快速連續(xù)地繪制屏幕的每個(gè)部分,一秒多次,以產(chǎn)生物體移動(dòng)的效果。?
其次,你會(huì)學(xué)會(huì)游戲循環(huán),一個(gè)游戲?qū)嶋H上是在繪制,獲取用戶(hù)輸入,處理游戲邏輯中間的有效的循環(huán)操作。?
第三,你會(huì)學(xué)會(huì)如何處理用戶(hù)的輸入,我之前從未注意過(guò)按下,按住,釋放一個(gè)按鍵或者鼠標(biāo)的細(xì)微差別,更不用說(shuō)處理雙擊操作了。另外你多久檢查一次用戶(hù)輸入?如果一直檢查,那游戲的其他部分就被凍結(jié),無(wú)法工作了。?
第四,你會(huì)學(xué)會(huì)如何創(chuàng)建和管理游戲中的對(duì)象,以及他們的狀態(tài)。例如如果動(dòng)態(tài)地創(chuàng)建一定數(shù)量的敵兵?工廠(chǎng)模式能幫助不少。?
第五,你會(huì)學(xué)會(huì)如何應(yīng)用游戲邏輯,什么時(shí)候更新子彈的位置?什么時(shí)候更多的敵兵應(yīng)該在屏幕上出現(xiàn),你如何得知敵人被消滅?什么時(shí)候游戲結(jié)束?我之前從未用過(guò)按模計(jì)算,現(xiàn)在我的游戲代碼中到處都是了。?
基本的游戲運(yùn)行起來(lái)以后,可以增加一點(diǎn)屏幕菜單,游戲結(jié)束的畫(huà)面,探索如何實(shí)現(xiàn)有點(diǎn)兒智能的敵兵,如果還覺(jué)得不夠的話(huà),還可以增加材質(zhì),聲音,在線(xiàn)的多個(gè)玩家!?
能學(xué)到的東西:?
-
屏幕繪制?
-
獲取用戶(hù)輸入?
-
游戲循環(huán)?
-
創(chuàng)建和管理動(dòng)態(tài)數(shù)量的物體?
-
狀態(tài)機(jī)?
-
播放聲音,使用材質(zhì), 網(wǎng)絡(luò)功能?
進(jìn)一步閱讀:
《游戲編程模式》
https://gameprogrammingpatterns.com/contents.html?
《Data Structures for Game Programmers》?
《Programming Game AI by Example》?
我從8個(gè)視頻游戲中學(xué)到的8個(gè)教訓(xùn)?
http://web.eecs.utk.edu/~azh/blog/8lessons8games.html?
編譯器- Tiny BASIC?
我做過(guò)的最引人注目的項(xiàng)目是編譯器,時(shí)至今日,如果我周日的下午有空編程的話(huà),我仍然回去寫(xiě)編譯器。?
通過(guò)創(chuàng)造一個(gè)東西,使得別人能創(chuàng)造更多東西,這種感覺(jué)實(shí)在太棒了。?
通過(guò)實(shí)現(xiàn)一個(gè)編譯器,我必須得學(xué)習(xí)很多復(fù)雜的編譯器技術(shù),這些技術(shù)通常來(lái)說(shuō)根本想不到。我建議從零開(kāi)始寫(xiě)編譯器,并且從一個(gè)很小的BASIC-like的語(yǔ)言開(kāi)始(例如Tiny BASIC,https://en.wikipedia.org/wiki/Tiny_BASIC ),然后把它編譯成你所熟悉的語(yǔ)言。?
例如,你可以用Python寫(xiě)一個(gè)編譯器,把Tiny Basic編譯為C#代碼, 不需要輸出成匯編,這能讓你專(zhuān)注到編譯器本身。
編譯器的第一個(gè)障礙就是如何做詞法分析,然后你需要構(gòu)建一顆抽象語(yǔ)法樹(shù),遞歸下降是個(gè)非常漂亮的技術(shù)。?
接下來(lái)做語(yǔ)義分析,確保代碼是有意義的,規(guī)則會(huì)被遵守。最后輸出目標(biāo)代碼。?
不要被那些術(shù)語(yǔ)嚇住,編譯器有海量的資料,先讓你的基本的編譯器工作起來(lái),然后增加一些標(biāo)準(zhǔn)庫(kù)(如簡(jiǎn)單的2D圖形功能),優(yōu)化參數(shù)傳遞,改進(jìn)錯(cuò)誤提示。
最后,你應(yīng)該用自己的語(yǔ)言寫(xiě)一些例子程序,向全世界展示你的工作成果。?
可以學(xué)到的東西?
-
詞法分析?
-
語(yǔ)法分析?
-
遞歸下降分析?
-
抽象語(yǔ)法樹(shù)?
-
語(yǔ)義分析?
-
代碼優(yōu)化?
-
代碼生成?
進(jìn)一步閱讀
《Crafting Interpreters》
https://www.craftinginterpreters.com/contents.html
《Write an Interpreter in Go》
《Let's Build a Compiler 》
https://compilers.iecc.com/crenshaw/?
PeayBASIC source code :?
https://github.com/AZHenley/PeayBASIC?
迷你操作系統(tǒng)?
在課堂上,操作系統(tǒng)的數(shù)據(jù)結(jié)構(gòu)和算法看起來(lái)太抽象而沒(méi)啥用處。但實(shí)際上,他們是非常有用的。多年來(lái),我把操作系統(tǒng)的基本概念應(yīng)用到了廣闊的領(lǐng)域,如游戲編程,甚至預(yù)測(cè)人類(lèi)行為的模型。?實(shí)現(xiàn)一個(gè)操作系統(tǒng)能幫助我們深入地理解底層的情況。?
由于依賴(lài)硬件,所以剛開(kāi)始的時(shí)候,學(xué)習(xí)曲線(xiàn)陡峭,有不少障礙,但是如果跟隨一本書(shū)或者教程,你可以快速地得到一個(gè)可以啟動(dòng)工作的OS,并且能運(yùn)行你自己的程序。?
我強(qiáng)烈推薦這本免費(fèi)的書(shū)籍:《Making a RISC-V Operating System using Rust.》?
需要學(xué)習(xí)的內(nèi)容?
-
交叉編譯?
-
操作系統(tǒng)自舉?
-
BIOS?
-
中斷?
-
x86 modes?
-
內(nèi)存管理和分頁(yè)?
-
調(diào)度(e.g., round robin)?
-
文件系統(tǒng) (e.g., FAT)?
進(jìn)一步閱讀:?
OSDev.org's wiki of resources?
https://wiki.osdev.org/Main_Page?
Making a RISC-V Operating System using Rust?
http://osblog.stephenmarz.com/index.html?
《操作系統(tǒng)概念》?
如果你能走到這一步,已經(jīng)非常厲害了,但是....?
如果你覺(jué)得還是不夠難,試試這兩個(gè):?
電子表格 ?
電子表格(例如Excel),把文本編輯器和編譯器這兩大挑戰(zhàn)結(jié)合起來(lái)了, 需要學(xué)會(huì)怎么表示單元格的內(nèi)容,并且實(shí)現(xiàn)一個(gè)解釋器,以便對(duì)單元格的內(nèi)容進(jìn)行公式計(jì)算。?
進(jìn)一步閱讀:?
有向無(wú)環(huán)圖?
https://en.wikipedia.org/wiki/Directed_acyclic_graph?
反應(yīng)式編程?
https://en.wikipedia.org/wiki/Reactive_programming?
《Spreadsheet Implementation Technology》?
視頻游戲控制臺(tái)模擬器?
為視頻游戲?qū)懸粋€(gè)模擬器(或者虛擬機(jī))把編譯器和操作系統(tǒng)的挑戰(zhàn)給結(jié)合起來(lái)了,當(dāng)你把別人的游戲在你的模擬器上運(yùn)行起來(lái)以后,那種成就感相當(dāng)棒。?
這個(gè)模擬器其實(shí)就是虛擬機(jī),能讓那些游戲以為自己在真實(shí)的CPU和其他硬件上運(yùn)行,難度相當(dāng)高。我建議從模擬CHIP-8開(kāi)始,這是一個(gè)簡(jiǎn)單的虛擬控制臺(tái),然后再轉(zhuǎn)移到一個(gè)真正的視頻游戲控制臺(tái)。
NES、SNES、Gameboy和Gameboy的高級(jí)版本都是可以模擬的,已經(jīng)有了大量的文檔和開(kāi)源模擬器。盡管它們都有自己的怪癖,使事情變得有趣(例如,某些游戲可能依賴(lài)于特定硬件的無(wú)文檔記錄的bug /特性)。還有PICO-8,它已經(jīng)成為一個(gè)非常有利可圖的“幻想”游戲機(jī)。?
進(jìn)一步閱讀:?
Writing a Chip-8 emulator?
https://aymanbagabas.com/2018/09/17/chip-8-emulator.html?
JavaScript Chip-8 Emulator?
http://blog.alexanderdickson.com/javascript-chip-8-emulator?
《How to Emulate a Game Boy》
https://blog.ryanlevick.com/DMG-01/public/book/
PyBoy source code?
https://github.com/Baekalfen/PyBoy?
后記:我覺(jué)得這篇文章列舉的項(xiàng)目都偏重基礎(chǔ),非常適合在校的大學(xué)生,可以鍛煉最基本的編程能力,建議多做幾個(gè)。如果已經(jīng)工作了,很難會(huì)有大塊的時(shí)間去折騰了,可以考慮選一個(gè)自己最感興趣的去實(shí)現(xiàn)。
?
原文鏈接:
http://web.eecs.utk.edu/~azh/blog/challengingprojects.html
總結(jié)
以上是生活随笔為你收集整理的每个程序员都应该挑战的6个项目的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 记住这两幅重要的图
- 下一篇: 做一个完整的Java Web项目太难了,