1次元セルオートマトン
提供:kuhalaboWiki
(版間での差分)
(1人の利用者による、間の5版が非表示) | |||
1行: | 1行: | ||
+ | == openFrameworksのサンプル == | ||
+ | |||
Wolframのセルオートマトンの描画プログラム | Wolframのセルオートマトンの描画プログラム | ||
25行: | 27行: | ||
for(int j = 1; j < NUM; j++){ // j: 時間 | for(int j = 1; j < NUM; j++){ // j: 時間 | ||
for(int i = 1; i < NUM-1; i++){ // i: 位置 | for(int i = 1; i < NUM-1; i++){ // i: 位置 | ||
− | cell[i][j] = ( cell[i-1][j-1] + cell[i+1][j-1] ) % 2; | + | cell[i][j] = ( cell[i-1][j-1] + cell[i+1][j-1] ) % 2; //状態遷移則 %は剰余演算 |
} | } | ||
} | } | ||
41行: | 43行: | ||
} | } | ||
} | } | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | ;状態遷移則を変えてみる。 | ||
+ | :1つ前と自分の値と1つ後の値を足した値 | ||
+ | <pre> | ||
+ | cell[i][j] = ( cell[i-1][j-1] + cell[i][j-1] + cell[i+1][j-1] ) % 2; | ||
+ | </pre> | ||
+ | |||
+ | :cellの値を256で割った余りにする。 | ||
+ | <pre> | ||
+ | cell[i][j] = ( cell[i-1][j-1] + cell[i+1][j-1] ) % 256; | ||
+ | </pre> | ||
+ | |||
+ | ;drawを変えてみる。 | ||
+ | :1つ前と自分の値と1つ後の値を足した値 | ||
+ | <pre> | ||
+ | if (cell[i][j] > 0) ofSetColor(127, cell[i][j], 0); //セルが 1 の時の描画色 | ||
</pre> | </pre> | ||
2020年10月31日 (土) 00:22時点における最新版
目次 |
[編集] openFrameworksのサンプル
Wolframのセルオートマトンの描画プログラム
[編集] シンプルに配列だけで記述
[編集] シェルピンスキーのギャスケット その1
- 2次元配列cell[256][256]を作り、まとめて状態を更新し、描画する。
#include "ofApp.h" static const int NUM = 256; //セルの個数 int cell[NUM][NUM]; //-------------------------------------------------------------- void ofApp::setup(){ ofBackground(0, 0, 0); //背景色の設定 //初期状態は真ん中だけが 1 で残りはすべて 0 for(int i = 0; i < NUM; i++){ cell[i][0] = 0; } cell[NUM/2][0] = 1; } //-------------------------------------------------------------- void ofApp::update(){ //状態遷移則 1つ前と1つ後の値を足した値の1桁目(2進法の足し算 XOR) for(int j = 1; j < NUM; j++){ // j: 時間 for(int i = 1; i < NUM-1; i++){ // i: 位置 cell[i][j] = ( cell[i-1][j-1] + cell[i+1][j-1] ) % 2; //状態遷移則 %は剰余演算 } } } //-------------------------------------------------------------- void ofApp::draw(){ int w = 4; //セルの描画幅 for(int i = 0; i < NUM; i++){ for(int j = 0; j < NUM; j++){ if( cell[i][j] > 0 ) ofSetColor(255,0,0); //セルが 1 の時の描画色 else ofSetColor(0,0,0); //セルが 0 の時の描画色 ofRect(i * w, j * w , w , w ); } } }
- 状態遷移則を変えてみる。
- 1つ前と自分の値と1つ後の値を足した値
cell[i][j] = ( cell[i-1][j-1] + cell[i][j-1] + cell[i+1][j-1] ) % 2;
- cellの値を256で割った余りにする。
cell[i][j] = ( cell[i-1][j-1] + cell[i+1][j-1] ) % 256;
- drawを変えてみる。
- 1つ前と自分の値と1つ後の値を足した値
if (cell[i][j] > 0) ofSetColor(127, cell[i][j], 0); //セルが 1 の時の描画色
[編集] クラスを使って記述
[編集] シェルピンスキーのギャスケット その2
クラスに、内部状態、状態遷移則などを定義する。
- Cell.h
- Cellクラスを設計
#pragma once #include "ofMain.h" class Cell { public: ofPoint pos; //位置 float width; //幅 ofColor bcolor; //描画色 int state; //内部状態 int sXXX; //自分と両隣りの状態 000-111(0-7)の8通り public: Cell(); void draw(); void update(); };
- Cell.cpp
- ルール90(01011010)の規則を記述
#include "Cell.h" Cell::Cell(){ width = 4; bcolor = ofColor(255, 0, 0); } void Cell::update(){ //自分と両隣りの状態に応じて次の自分の状態を決める switch(sXXX){ case 0: //000 state = 0; break; case 1: //001 state = 1; break; case 2: //010 state = 0; break; case 3: //011 state = 1; break; case 4: //100 state = 1; break; case 5: //101 state = 0; break; case 6: //110 state = 1; break; case 7: //111 state = 0; break; } } void Cell::draw(){ if( state ){ ofSetColor(bcolor); ofRect(pos, width,width); } }
- ofApp.h
- クラスの配列cellを生成。その1の通常の配列cellとの違いに注意。
#pragma once #include "ofMain.h" #include "Cell.h" class ofApp : public ofBaseApp{ public: void setup(); void update(); void draw(); void keyPressed(int key); void keyReleased(int key); void mouseMoved(int x, int y ); void mouseDragged(int x, int y, int button); void mousePressed(int x, int y, int button); void mouseReleased(int x, int y, int button); void windowResized(int w, int h); void dragEvent(ofDragInfo dragInfo); void gotMessage(ofMessage msg); static const int NUM = 256; //セルの個数 Cell cell[NUM][NUM]; };
- ofApp.cpp
//-------------------------------------------------------------- void ofApp::setup(){ ofBackground(0, 0, 0); //背景色の設定 //初期状態は真ん中だけが 1 で残りはすべて 0 for(int i = 0; i < NUM; i++){ cell[i][0].state = 0; cell[i][0].pos = ofPoint(i * cell[i][0].width, 0); } cell[NUM/2][0].state = 1; } //-------------------------------------------------------------- void ofApp::update(){ for(int j = 1; j < NUM; j++){ for(int i = 0; i < NUM; i++){ int iP = (i - 1 + NUM ) % NUM; int iN = (i + 1 + NUM ) % NUM; // 自分と両隣りの状態の2進数000-111を10進数0-7に変換 cell[i][j].sXXX = cell[iP][j-1].state * 4 + cell[i][j-1].state * 2 + cell[iN][j-1].state; cell[i][j].update(); cell[i][j].pos = ofPoint(i * cell[i][j].width, j * cell[i][j].width); //セルの描画位置を指定 } } } //-------------------------------------------------------------- void ofApp::draw(){ for(int i = 0; i < NUM; i++){ for(int j = 0; j < NUM; j++){ cell[i][j].draw(); } } }
[編集] 256種のルールのセルオートマトン
- 256種類のルール全てのセルオートマトンを順番に表示する。
- Cell.h
#pragma once #include "ofMain.h" class Cell { public: ofPoint pos; //位置 float width; //幅 ofColor bcolor; //描画色 int state; //内部状態 int sXXX; //次の状態 000-111の8通り int rX8; //ルール 8bit 256通り public: Cell(); void draw(); void update(); };
- Cell.cpp
#include "Cell.h" Cell::Cell(){ width = 4; bcolor = ofColor(255, 0, 0); } void Cell::update(){ //自分の次の状態00000000-11111111の256通りを10進数から2進数に変換 switch(sXXX){ case 0: //000 state = rX8 % 2; break; case 1: //001 state = ( rX8 % 4) / 2; break; case 2: //010 state = ( rX8 % 8) / 4; break; case 3: //011 state = ( rX8 % 16) / 8; break; case 4: //100 state = ( rX8 % 32) / 16; break; case 5: //101 state = ( rX8 % 64 ) / 32; break; case 6: //110 state = ( rX8 % 128 ) / 64; break; case 7: //111 state = rX8 / 128; break; } } void Cell::draw(){ if( state ){ ofSetColor(bcolor); ofRect(pos, width,width); } else { ofSetColor(ofColor(0, 0, 0)); ofRect(pos, width,width); } }
- 10進数から2進数の変換
- 10進数 n を2進数に変換した時の2^kの位の値は ( n % 2^(k+1) ) / 2^k で表せる。
- ofApp.h
#pragma once #include "ofMain.h" #include "Cell.h" class ofApp : public ofBaseApp{ public: void setup(); void update(); void draw(); void keyPressed(int key); void keyReleased(int key); void mouseMoved(int x, int y ); void mouseDragged(int x, int y, int button); void mousePressed(int x, int y, int button); void mouseReleased(int x, int y, int button); void windowResized(int w, int h); void dragEvent(ofDragInfo dragInfo); void gotMessage(ofMessage msg); static const int NUM = 256; //セルの個数 Cell cell[NUM][NUM]; int r; //ルール番号 0-255の10進値 };
- ofApp.cpp
#include "ofApp.h" //-------------------------------------------------------------- void ofApp::setup(){ ofBackground(0, 0, 0); //背景色の設定 ofSetFrameRate(2); //フレームレイト設定 r = 0; //ルール番号の初期値 //初期状態は真ん中だけが 1 で残りはすべて 0 for(int i = 0; i < NUM; i++){ cell[i][0].state = 0; cell[i][0].pos = ofPoint(i * cell[i][0].width, 0); } cell[NUM/2][0].state = 1; } //-------------------------------------------------------------- void ofApp::update(){ r = ( r + 1 ) % 256; //ルール番号を1つ増やす。256になったら0に戻す for(int j = 1; j < NUM; j++){ for(int i = 0; i < NUM; i++){ cell[i][j].rX8 = r; int iP = (i - 1 + NUM ) % NUM; int iN = (i + 1 + NUM ) % NUM; cell[i][j].sXXX = cell[iP][j-1].state * 4 + cell[i][j-1].state * 2 + cell[iN][j-1].state; cell[i][j].update(); cell[i][j].pos = ofPoint(i * cell[i][j].width, j * cell[i][j].width); cell[i][j].bcolor = ofColor(255-r, i, j); //模様にグラデーションをつける } } } //-------------------------------------------------------------- void ofApp::draw(){ for(int i = 0; i < NUM; i++){ for(int j = 0; j < NUM; j++){ cell[i][j].draw(); } } // ルール番号の表示 ofSetColor(ofColor::white); ofDrawBitmapString("rule: " + ofToString(r), 10, 20); }