精選文章
- 取得連結
- X
- 以電子郵件傳送
- 其他應用程式
2026 和 AI 一起寫程式 - 4. 沙堆模型 Abelian Sandpile Model 曼陀羅 Mandala
前篇:2026 和 AI 一起寫程式 - 3 井字遊戲 - 1 kotlin 2.3
Github - https://github.com/neojou/sandpile
這次我們來玩一個超經典的複雜系統模型:Abelian Sandpile Model(阿貝爾沙堆模型,也叫 BTW 模型)。規則簡單到不行——每個格子堆沙粒,≥4 就「崩塌」分給四個鄰居——卻能從隨機加沙中自動長出高度對稱、層層放射的圖案,很多人直接叫它「沙堆曼陀羅 」(sandpile mandala)。
我用 Kotlin +
WebAssembly(Wasm)把它實作出來,讓瀏覽器直接跑,還能互動加沙看它成長。成品
Demo 放這裡:
👉 https://neojou.github.io/mandala/sandpile
先簡單科普:什麼是 Abelian Sandpile Model?
(詳細版見我另一篇:沙堆模型完整介紹)
這個模型 1987 年由 Per Bak、Chao Tang、Kurt Wiesenfeld 提出,原本想解釋自然界的 1/f 噪聲(粉紅噪聲),結果意外開啟了「自組織臨界性」(Self-Organized Criticality, SOC)的概念。
規則超簡單:
- 格子世界,每格有整數高度(沙粒數) z(i,j)
- 隨機選一格加 1 粒沙
- 如果某格 z ≥ 4,就「崩塌」:自己減 4,四個鄰居(上、下、左、右)各 +1
- 連鎖反應繼續,直到所有格子 < 4 才穩定
關鍵特性:
- Abelian(阿貝爾性):崩塌順序不影響最終結果(Deepak Dhar 1990 年證明)
- 系統自動趨向「臨界狀態」,小加沙可能引發大「雪崩」(avalanche),雪崩大小呈冪律分佈
- 最神奇玩法:只從正中央一直加沙,跑幾千到幾萬次,就會長出近似曼陀羅的對稱圖案——同心圓層次、放射臂、甚至 fractal 細節!
為什麼會長出「曼陀羅」?(藝術與數學的奇妙連結)
詳細曼陀羅介紹見:曼陀羅 - 從宗教藝術到科學模型
曼陀羅(Mandala,梵文「圓圈」)本是佛教/印度教的宇宙象徵圖,以中心放射對稱、層層展開為特徵。科學上,它涉及對稱群(群論)、分形自相似。
沙堆模型為什麼這麼像?
- 從中心持續加沙 → 強制中心對稱
- 崩塌規則是 Laplacian-like(離散拉普拉斯算子),自然產生放射/同心結構
- 穩定態: 尤其是 recurrent configurations)常出現 90° 旋轉對稱
- 顏色映射(高度、崩塌計數)後,視覺上直接變成「數學曼陀羅」
很多人用它生成藝術、冥想圖,甚至哲學上呼應「簡單規則湧現複雜秩序」——跟佛教「緣起性空」有點異曲同工之妙 ^^。
我的實作過程:Kotlin + Wasm 怎麼做?
系列目標是用現代工具重現經典模型,讓瀏覽器直接跑,不裝任何東西。
而這是 Kotlin Multiplatform , 如一開始這篇 井字遊戲 所述,
將來打算擴展到 Android 和 iOS
為什麼選 Kotlin + Wasm?
- Kotlin 語法現代、null-safe、多平台(我之前用在 Android、桌面、Web)
- Kotlin/Wasm 編譯到 WebAssembly,效能接近原生,比純 JS 快很多(尤其大格子崩塌迴圈)
- 與 JS Canvas 互操作簡單
核心資料結構
- 用 IntArray 存 2D 格子
- 採用 Android 常見的 MVVM 架構, SandpileBoard 物件負責計算
- 參考人的視覺殘留, 定時 25ms 才做一個 snapshot 給 View Model, 而不是每顆沙粒算完就畫一張, 這樣大幅提升了整體的效能
崩塌演算法 用 Queue 處理待崩塌格子(BFS 風格,避免遞迴 stack overflow):
fun topple() {
while (unstable.isNotEmpty()) {
val (x, y) = unstable.removeFirst()
if (grid[x * width + y] < 4) continue
grid[x * width + y] -= 4
// 四鄰 +1,邊界可吸沙(或反射/開放)
if (x > 0) { grid[(x-1)*width + y]++; if (grid[(x-1)*width + y] == 4) unstable.add((x-1) to y) }
if (x < height-1) { ... }
if (y > 0) { ... }
if (y < width-1) { ... }
// 記錄崩塌次數(用來畫熱圖曼陀羅)
collapseCount[x * width + y]++
}
}渲染
- 用 Canvas 2D context
- 顏色映射:依照高度 0–3 設計顏色讓曼陀羅更華麗,
將來色盤可以自訂, 如灰階,彩虹或火山色階
- 互動:目前是自動從中心加,將來可以改成隨機,或動態指定位置
遇到的坑:
高度不對問題
第二種方式的寫法:
推薦合適的 index.html - Github
執行:
原本:
現在:
成果展示 & 互動玩玩看
直接點這裡跑:https://neojou.github.io/mandala/sandpile
延伸:這模型還能幹嘛?
- 物理:模擬地震、森林火、股市崩盤
- 數學:sandpile group(有限阿貝爾群)、身份元素(加到 identity 會回到原態)
- 藝術:生成 NFT、分形壁紙
- AI 交叉:臨界學習、神經網路 avalanches
未來想試:3D 沙堆、聲音映射(崩塌當音階)、更大格子用 WebGL。
結語
用最簡單規則,卻能長出宇宙級對稱美感——這就是複雜系統的魅力。我跟 AI 一起 debug、優化、配色,過程超有趣!
GitHub 原始碼:https://github.com/neojou/sandpile
歡迎 fork、star、提 issue,一起玩沙!
下一集再見~(預告:可能玩 Game of Life 或其他 cellular automata?)
- 取得連結
- X
- 以電子郵件傳送
- 其他應用程式








留言
張貼留言