簡介
最早接觸蘭頓螞蟻是在做參數化的時候,那時候隻感覺好奇,以為是很複雜的東西。因無意中看到生命遊戲的 React 實作,是以希望通過蘭頓螞蟻的例子再學習一下 React。
蘭頓螞蟻的規則非常簡單:
如果螞蟻位于白色方塊,則向右旋轉 90°,反轉方塊的顔色,然後向前移動一步。
如果螞蟻位于黑色方塊,則向左旋轉 90°,反轉方塊的顔色,然後向前移動一步。
如下圖所示:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiYWan5iNwQDM2kDNxUTMtYDN4MjMxQjMyEjMyEDOxAjMtUDN0kTO58CXyEDOxAjMvwVN0QTO5kzLcd2bsJ2Lc12bj5ycn9Gbi52YugTMwIzZtl2Lc9CX6MHc0RHaiojIsJye.gif)
螞蟻在前一百步有一定規律,之後陷入混沌,直到一萬步之後将走出混沌形成一條高速公路。
蘭頓螞蟻和生命遊戲都是元胞自動機的一種,關于蘭頓螞蟻的更多介紹可以看維基百科
開始編寫程式
在本教程中,我主要還是說一下項目中的問題及難點,不會對整個項目做太詳細的介紹,把代碼粘貼一遍也沒什麼意義,大家可以自己摸索一遍,其中 Webpack 用了 4.0,順便說一句,Webpack4.0 還是有不少坑的,項目在 GitHub 中有,遇到問題可以翻閱一下源代碼
源碼:https://github.com/nzbin/langton-ant-redux
先看一下最終效果的動圖示範:
這個項目可以說是 React + Redux 非常基礎的練習。主要就是繪制網格,根據螞蟻規則重繪網格。以下是項目目錄:
src
├── actions
│ └── index.js
├── components
│ ├── app.js
│ ├── button.js
│ └── cell.js
├── containers
│ ├── board.js
│ ├── control.js
│ └── counter.js
├── reducers
│ ├── index.js
│ ├── reducer_board.js
│ ├── reducer_generations.js
│ └── reducer_play_status.js
└── index.js
螞蟻法則的算法
蘭頓螞蟻示範程式的關鍵就是螞蟻規則的算法,其實算法也很簡單,設定方向變量,模拟螞蟻的前進線路即可。以下是邏輯代碼:
// status: true -> black square
if (gameState[row][col].status) {
gameState[row][col].status = false;
// ant: turnLeft90 -> move forward 1 step
switch (dir) {
case 'T':
ant['pos'] = [row, col - 1];
ant['dir'] = 'L';
break;
case 'B':
ant['pos'] = [row, col + 1];
ant['dir'] = 'R';
break;
case 'L':
ant['pos'] = [row + 1, col];
ant['dir'] = 'B';
break;
case 'R':
ant['pos'] = [row - 1, col];
ant['dir'] = 'T';
break;
default:
}
}
// status: false -> white square
else if (!gameState[row][col].status) {
gameState[row][col].status = true;
// ant: turnRight90 -> move forward 1 step
switch (dir) {
case 'T':
ant['pos'] = [row, col + 1];
ant['dir'] = 'R';
break;
case 'B':
ant['pos'] = [row, col - 1];
ant['dir'] = 'L';
break;
case 'L':
ant['pos'] = [row - 1, col];
ant['dir'] = 'T';
break;
case 'R':
ant['pos'] = [row + 1, col];
ant['dir'] = 'B';
break;
default:
}
}
布局
示範程式的網格如果隻是寫死的話就非常簡單,但是為了有更好的體驗,我做成了響應式,無論有多少網格,總能全部顯示在螢幕上。看似很簡單的問題,其實有很多可以學習的地方。
制作響應式網格的方式有很多,比如結合媒體查詢,百分比。為了效果更好一點,我選擇了百分比。
其次正方形網格也有多種方式實作,比如 vw 機關,百分比+padding。其中使用 vw 機關會有一個問題,就是它的相對父元素是視窗,是以網格總是全屏顯示,比較惡心。最後使用了百分比+padding 的方式。細節方面還使用了 calc 運算。
但是百分比計算的網格存在精度問題,适當放大尺寸可以解決。
檢視線上 Demo:https://nzbin.github.io/langton-ant-redux
性能
因為我對 React 的研究不深,是以在這個項目中遇到了一些性能問題,繪制一個 100X100 的網格的話,在 FireFox 中明顯感覺到卡頓(與我的機子也有關系),Chrome 表現還可以。
其實用 canvas 做示範程式可能更好一些,同時跑多個螞蟻也沒有問題。
總結
因各種各樣的原因,沒想到這篇文章又拖了半年多才寫完,與其說是教程,不如說是對蘭頓螞蟻的介紹,更慚愧的是文章内容不深,無法幫助更多的初學者。我不是 React 的擁泵,目前專注 Angular,是以關于 React 的譯文以及簡易教程就到此為止吧。
感謝您的閱讀,如果您對我的文章感興趣,可以關注我的部落格,我是叙帝利,下篇文章再見!
開發低代碼平台的必備拖拽庫 https://github.com/ng-dnd/ng-dnd
基于 Angular Material 的中背景管理架構 https://github.com/ng-matero/ng-matero
Angular Material Extensions 擴充元件庫 https://github.com/ng-matero/extensions
仿 Windows 照片檢視器插件 https://github.com/nzbin/photoviewer
仿 Windows 照片檢視器插件 jQuery 版 https://github.com/nzbin/magnify
完美替代 jQuery 的子產品化 DOM 庫 https://github.com/nzbin/domq
簡化類名的輕量級 CSS 架構 https://github.com/nzbin/snack
與任意 UI 架構搭配使用的通用輔助類 https://github.com/nzbin/snack-helper
單元素純 CSS 加載動畫 https://github.com/nzbin/three-dots
有趣的 jQuery 卡片抽獎插件 https://github.com/nzbin/CardShow
懸疑科幻電影推薦 https://github.com/nzbin/movie-gallery
鍛煉記憶力的小程式 https://github.com/nzbin/memory-stake