Python 實現生命遊戲
作者:Pleiades
來源:http://www.cnblogs.com/pleiades/p/8353713.html
生命遊戲是英國數學家約翰·何頓·康威在1970年發明的細胞自動機。它包括一個二維矩形世界,這個世界中的每個方格居住著一個活著的或死了的細胞。一個細胞在下一個時刻生死取決於相鄰八個方格中活著的或死了的細胞的數量。如果相鄰方格活著的細胞數量過多,這個細胞會因為資源匱乏而在下一個時刻死去;相反,如果周圍活細胞過少,這個細胞會因太孤單而死去。
規則看起來很簡單,但卻能演繹出無窮無盡的內容。
滑翔者:每4個回合"它"會向右下角走一格。雖然細胞早就是不同的細胞了,但它能保持原本的形態。
輕量級飛船:它的周期是4,每2個回合會向右邊走一格。
脈衝星:它的周期為3,看起來像一顆周期爆發的星星。
更複雜的圖案。
來體會一下這些作品的腦洞以及震撼:
用生命遊戲實現生命遊戲:http://www.bilibili.com/video/av616329/index.html
生命遊戲的規則其實很簡單。我們可以把計算機中的宇宙想像成是一堆方格子構成的封閉空間,尺寸為N的空間就有NN個格子。而每一個格子都可以看成是一個生命體,每個生命都有生和死兩種狀態,如果該格子生就顯示藍色,死則顯示白色。每一個格子旁邊都有鄰居格子存在,如果我們把33的9個格子構成的正方形看成一個基本單位的話,那麼這個正方形中心的格子的鄰居就是它旁邊的8個格子。
每個格子的生死遵循下面的原則:
1. 如果一個細胞周圍有3個細胞為生(一個細胞周圍共有8個細胞),則該細胞為生(即該細胞若原先為死,則轉為生,若原先為生,則保持不變) 。
2. 如果一個細胞周圍有2個細胞為生,則該細胞的生死狀態保持不變;
3. 在其它情況下,該細胞為死(即該細胞若原先為生,則轉為死,若原先為死,則保持不變)
設定圖像中每個像素的初始狀態後依據上述的遊戲規則演繹生命的變化,由於初始狀態和迭代次數不同,將會得到令人嘆服的優美圖案。
我們用#代表活的細胞,空格表示死的細胞,那麼我們可以用控制台列印字元、清屏來模擬生命遊戲。我的代碼在github上:
https://github.com/Pleiades0428/GameOfLife/blob/master/Demo/gameOfLife.py
遊戲世界尺寸為60x20,隨機生成初始狀態,循環邊界,按任意鍵進入下一幀,q退出。
單純的看這段程序,好像並沒有什麼問題,代碼邏輯正確、清晰。
效果圖:
我們來嘗試一些python的高級特性,比如列表生成式。
例如,在生成初始值時,我們一般這樣寫:
如果用列表生成式,我們可以這樣寫:
注意這裡必須用global聲明,否則screen將默認作為函數內的局部變數。這裡用了兩層列表生成式來生成一個二維數組。
列表生成式很好很強大,如果用好能大大提高效率。但會犧牲一定的可讀性,如果單個表達式寫的過於複雜,那就變成write-only了。尤其是在團隊開發情況下,可讀性日益重要。
重寫後的代碼:
https://github.com/Pleiades0428/GameOfLife/blob/master/Demo/gameOfLife.1.py
如果僅僅是作為練習,這樣就已經足夠好了,簡潔易讀。
可是我們還不能滿足,我們來給生命插上面向對象的翅膀,在模塊化的天空中翱翔。對,就是讓他跟別的模塊搞對象!
先來定義一個類GameOfLifeWorld,之前那些醜陋的全局變數,讓他們統統變成成員變數,再也不能在外興風作浪。
然後把UI層剝離,只保留遊戲的核心邏輯。
代碼:
https://github.com/Pleiades0428/GameOfLife/blob/master/Demo/gameOfLifeWorld.py
有了上一步的鋪墊,我們終於可以讓Tkinter粉墨登場了。Tkinter是著名的UI庫,Python自帶的Tkinter是一個精簡版,不過也夠我們用的了。
我們這裡用到的主要是Canvas,Button控制項。Canvas畫布用來繪製遊戲區,Button用來交互。
代碼:
https://github.com/Pleiades0428/GameOfLife/blob/master/Demo/gameOfLifeWorld.py
效果:
以上就是這樣,項目我還會繼續改進,希望大家喜歡。
題圖:pexels,CC0 授權。
TAG:編程派 |