1. 程式人生 > >Conway生命遊戲

Conway生命遊戲

圖像 接口 per 有一個 c語言 當前 大於 戰爭 有著

  版權申明:本文為博主窗戶(Colin Cai)原創,歡迎轉帖。如要轉貼,必須註明原文網址

  http://www.cnblogs.com/Colin-Cai/p/9986679.html 

  作者:窗戶

  QQ/微信:6679072

  E-mail:[email protected]

  1970年,英國數學家Conway發明了生命遊戲。拋開元胞自動機的復雜概念,我們只是去感受一下二維的生命遊戲,這其實是元胞自動機的一個特例。

  

  生命遊戲

  

  我們先考慮有限的情況,對於mXn的方格,每個方格都會有一個狀態,該狀態有兩個可能值:有生命、無生命。

  技術分享圖片

  如上圖8X8的方格,紅色的格子代表狀態為有生命,白色的格子代表狀態為無生命。

  生命遊戲是一代一代的演化,每一代就是所有格子的一組狀態。我們來說演化規則,對於每個格子,我們來數這個格子所有的周圍格子狀態為由生命的數目。

  這裏的周圍格子是指:這個格子的上、下、左、右、左上、右上、左下、右下這8個格子。當然,有例外,角上的格子只有3個周圍格子,而邊上的格子只有5個周圍格子。

  於是,我們把上面這個圖的每個格子的周圍有生命格子數目標註出來。

  技術分享圖片

  下一代所有格子狀態由以下規則確定:

  1.如果周圍有生命格子的數目小於2,則下一代這個格子狀態為無生命(解釋為太孤單)。

  2.如果周圍有生命格子的數目大於3,則下一代這個格子為無生命(解釋為周圍生命太多,資源消耗厲害)。

  3.如果周圍有生命格子的數目等於2,則下一代這個格子的狀態繼續保持當前的狀態。

  4.如果周圍有生命格子的數目等於3,則下一代這個格子的狀態為有生命。

  

  於是,下一代應為如下:

  技術分享圖片

  

  把各代組成動畫如下:

  技術分享圖片

  只可惜這個到了第6代,所有的格子都變成無生命狀態。

  震蕩子

  有一類神奇的圖案,可以反復不斷的循環,稱為震蕩子。

  技術分享圖片

  上面這個震蕩子周期為15。

  槍型圖

  

  下面這個圖是Bill Gosper於1970年發現的第一個Gun,你看那一個個向右下方向而去的像不像“子彈"?實際上,Gun描述的是一個無限的方格,因為子彈是在不斷變多的,圖形的尺寸實際上會越來越大,但在有限的方格情況下其實是震蕩子(下圖實際上是虛擬的從無限的方格中截取的有限圖像)。

  技術分享圖片

  

  這是發現的第二個Gun。

  技術分享圖片

  以我的能力,我是完全不知道這兩個Gun是怎麽被拼出來的。

  

  程序實現

  生命遊戲規則簡單,我想在學習程序的過程中實現一個並不是什麽難事。

  我上面的這些動畫實際上也是用程序生成的,我推薦python用cv2庫,它屬於opencv,開發效率還是很高的。

  真想從底層動手,那就用C語言造輪子吧,只要體力好,也沒什麽不可以。

  如果要生成bmp,研究一下bmp文件的格式,wiki上就有,https://en.wikipedia.org/wiki/BMP_file_format

  如果想要jpeg,那麽可以使用libjpeg,只是libjpeg只有從bmp文件轉成jpeg,默認接口裏沒有從內存轉的,這可能不太方便,需要的話得自己來加個接口,很多年前我加過。

  

  計算周圍生命格子數目

  

  我想大部分的人來計算都是對於某個點,依次數周圍的格子,然後挨個相加,從而計算整個矩陣的加法數量的線性系數是7(因為大多格子周圍都是8個格子,要做7次加法),也就是加法數量除以矩陣規模(節點數)的極限為7。

  如果只從加法數量來說,這個規模不能讓人滿意。下面這個方法會好很多。

  第一步,同行的兩兩結對相加。

  技術分享圖片

  a0,0+a0,1 a0,2+a0,3 a0,4+a0,5 ...

  ...

  an,0+an,1 an,2+an,3 an,4+an,5 ...

  ...

  這樣使用線性系數0.5次加法

  

  第二步,每個格子再多加一次得到這個格子自身和左、右兩格的和。

  技術分享圖片

  顯然,這次使用加法數量系數為1。

  於是我們看到了,使用系數為1.5的加法數量就完成了每個格子自身和左、右兩格的和,而本來平凡的手段這個系數為2。

  第三步,在此基礎上,使用第一步、和第二步,只是第一步和第二步從矩陣的橫向考慮,現在統統改成縱向。

  技術分享圖片

  這樣就得到了每個格子以自身為中心的九宮格的九個格子之和。

  這樣累計一下,系數翻個倍,為3。

  第四步,上面其實多加了自身這個格子,於是減掉自身。

  系數就變成4,比之前7要好。

  以上只是簡單的說一說道理,而真正在優化卷積、中值濾波等應用的時候,要比這個復雜的多。

  稀疏矩陣

  先放個動畫。

  技術分享圖片

  我們似乎在上述動畫中看到了星際戰爭^_^

  圖像中大多數格子的狀態都是無生命,這種情況下,如果還是依次去計算矩陣的每一個格子,是個很大的浪費。

  實際上,我們只需要記錄其中狀態為有生命的格子就行了,這是因為,下一代有生命的格子就在這一代有生命的格子的近旁。

  這就是稀疏矩陣的出發點,當然,稀疏矩陣本身有著非常多的算法,基本都是本著相近的元素會發生相互作用,從而相近的元素要給予更為快速的查找。對於完全無序的集合,稀疏矩陣的元素一旦多起來,效率非常低下。

  有興趣的就自己去研究吧,比如四叉樹就是常用的空間索引。

  

  

Conway生命遊戲