聊聊開工這一周
職業生涯
自從步入職場,我就一直思考自己的職業生涯應該怎麼走。開過很多腦洞,有過很多的想法,也帶來很多困擾和焦慮。其中最大的原因是能力跟不上眼光,看得太遠,走的太慢,心中萬分急躁。在這曲折的思索糾結過程,同時也給了我更寬的視野和更多的思路,慢慢摸索出自己想走的方向。
找准方向後,今年我給自己定的基調是:沉澱和發散。沉澱,是指在技術方面,把基礎繼續夯實,逐漸成長為有豐富經驗的開發者,對底層、對組件的理解,要比過去再深入一層。發散,則是我希望自己能在業餘時間,學習變成一個優秀的獨立遊戲開發者。為什麼是「遊戲開發者」,除了我目前從事的是遊戲開發之外,下面會聊到更多的原因。
演算法
這周開始我的第三次刷 leetcode 計劃。沒錯,前兩次都有各種原因(借口)半途而廢。這次告訴自己一定要堅持下來。分享一道這周刷到的有意思的題目:《Median of Two Sorted Arrays》。題意是找出兩個有序數組的中位數,要求是 log(m+n)。一看到 log(m+n),我就知道要用二分法,但思路就止步於此了,最後還是參考了別人的做法才做出來(如下圖)。這周刷題還是有點心得的,以前覺得演算法太過理論化,實際工作中不太會用到。但最近在思考一些需求的時候,明顯感覺到自己在演算法這方面的不足,對演算法的不熟悉,使我在設計方案時太過依賴各種組件的能力。演算法還是得好好加強鞏固下。
架構
由於早上起不來,時間有限,只讀了一兩篇 engineering blog。分享一篇比較有意思的:《Client-side ranking to more efficiently show people stories in feed》。角度新穎,在客戶端對 feed 流的展示順序做優化,以提高用戶體驗。實現方案看起來不難,但卻是個比較特別的做法。
閱讀
這周大部分業餘時間都在讀《Linker & Loader》。還沒讀完,覺得不太好懂,但可以把之前讀《操作系統》、《Linux 內核設計與實現》的一些知識點拼接起來,讓自己有更整體的理解。
另外整理之前讀《操作系統》的讀書筆記的時候,偶然讀到一句話:「如果能把文件看成是一種地址空間,那麼就離理解文件不遠了」。這句話點醒了我,如果把文件比做虛擬地址空間,文件的磁碟地址比做內存物理地址,文件通過 inode 來管理映射關係,而類似的虛擬內存由頁表來管理映射關係。這麼看來,磁碟和內存,本質上都用了相同的抽象方法。
最後在放鬆時間讀的書是《遊戲設計夢工廠》。對於一個從來沒有關注過遊戲策劃的技術人,我覺得這本書太適合入門遊戲設計了。首先這本書是實打實的介紹了遊戲設計的理論,為什麼這一點很重要,因為學習計算機這條路就是充滿了理論、規範和模式,所以我已經習慣了理論+實踐的學習方法。以前我嘗試理解產品策劃做事的方法論,總覺得太過感性而沒有理論的支持。而這本書很好的介紹了遊戲設計的流程、遊戲的構成。比如把遊戲分成:玩家、目標、行為、規則、資源、衝突、邊界和結構這幾種正規元素。當我嘗試設計一個遊戲時,我不會去直接複製某個已有遊戲的玩法,而會去思考我的遊戲的目標是什麼?允許玩家可以有哪些行為?應該制定哪些規則?有了理論的指導,讓我可以用更加上層的角度看待問題。
為什麼想做獨立遊戲開發者,因為遊戲設計不像是編程,編程遵循範式,套用模式。遊戲雖然有理論基礎,但需要遊戲設計者在此基礎上發散、創新。設計遊戲需要對歷史、人文、經濟等等各個領域都有些了解,遊戲設計也時常從生活中汲取靈感。對我來說,這和編程帶給我的是非常不同的體驗。我希望設計遊戲的過程能讓自己更近貼近生活,更大膽去學習其他領域,去突破自己。
電影
周末看了部電影《俠探傑克》,但想聊的不是電影本身,而是看電影中忽然冒出的聯想。在讀《遊戲設計夢工廠》的時候,提到玩家的交互模式有:
- 單人玩家 vs 遊戲系統
- 多名獨立玩家 vs 遊戲系統
- 玩家 vs 玩家
- 單邊對抗
- 多邊對抗
- 協作遊戲
- 團隊競爭
在看到《俠探傑克》中 傑克和反派頭牌 pk 的時候,忽然發現這類電影的模式也能夠歸類到遊戲中玩家的交互模式,例如《俠探傑克》屬於玩家 vs 玩家(反派頭牌挺強的,歸類為玩家對玩家),《美隊3》屬於團隊競爭(分成兩個陣營對打),《颶風營救》屬於單個玩家 vs 遊戲系統(反派都是小嘍啰,我歸類為遊戲系統)。唔,這波可能腦洞有點大..哈哈
工作
今年任重道遠,雖然目前具體任務還沒安排下來,趁著有空我也稍微思考了些潛在的需求。一個比較有挑戰的是全區實時排行榜。全區意味著海量,數據量大全部都實時做排序必定不現實。我想的方案是分段,按段位不同做不同的排序策略。排名靠前的段位做實時排序,其餘段位做模糊排序(只給百分比)。所以關鍵點在於如何快速算出玩家的段位。
假設排序的 key 是分數,最高分是 10w。我的思路是用桶排序。定義一個長度為 10w 的數組:
int score[100000];
玩家的分數為數組索引。假設我玩了 9w 分,那麼更新該數組:
score[90000]++;
這樣只需要遍歷下該數組就知道玩家的大致段位:
float get_percent(query_score) {
pass_people = 0; // 引用
total_people = 0; // 引用
for (score = MAX_SCORE; score >= 0; score--) {
if (score > query_score) { pass_people++; }
total_people++;
}
return float(pass_people)/total_people;
}
這樣就可以很方便的實現分段實時排行。例如在前 1% 的玩家才做實時排序,後面的玩家只返回排名的百分比。這個方案應該還有我沒想到的點,歡迎大家討論。
結束語
寫完流水賬,最後硬廣一波,歡迎大家踩下我的博客。博客的定位偏向技術文章,後續我會繼續在知乎寫寫平時的想法,歡迎大家一起交流~
推薦閱讀:
※寫程序得女友——日本OJ Paiza Online Hackathon小遊戲"戀愛SLG"題解
※浙江大學-數據結構-應用實例:最大子列和問題-1.3
※薦書:《編碼:隱匿在計算機軟硬體背後的語言》
※人工智慧可以擁有靈魂嗎?