1次元セルオートマトン
提供:kuhalaboWiki
(版間での差分)
(→シェルピンスキーのガスケット) |
|||
| (1人の利用者による、間の34版が非表示) | |||
| 1行: | 1行: | ||
| + | == openFrameworksのサンプル == | ||
| + | |||
Wolframのセルオートマトンの描画プログラム | Wolframのセルオートマトンの描画プログラム | ||
| − | == | + | == シンプルに配列だけで記述 == |
| − | === | + | === シェルピンスキーのギャスケット その1 === |
| + | * 2次元配列cell[256][256]を作り、まとめて状態を更新し、描画する。 | ||
<pre> | <pre> | ||
#include "ofApp.h" | #include "ofApp.h" | ||
| 22行: | 25行: | ||
void ofApp::update(){ | void ofApp::update(){ | ||
//状態遷移則 1つ前と1つ後の値を足した値の1桁目(2進法の足し算 XOR) | //状態遷移則 1つ前と1つ後の値を足した値の1桁目(2進法の足し算 XOR) | ||
| − | for(int j = 1; j < NUM; j++){ | + | for(int j = 1; j < NUM; j++){ // j: 時間 |
| − | for(int i = 1; i < NUM-1; 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; //状態遷移則 %は剰余演算 |
} | } | ||
} | } | ||
| 42行: | 45行: | ||
</pre> | </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> | ||
| + | |||
| + | == クラスを使って記述 == | ||
| + | === シェルピンスキーのギャスケット その2 === | ||
| + | クラスに、内部状態、状態遷移則などを定義する。 | ||
;Cell.h | ;Cell.h | ||
| + | * Cellクラスを設計 | ||
<pre> | <pre> | ||
#pragma once | #pragma once | ||
| 57行: | 79行: | ||
ofColor bcolor; //描画色 | ofColor bcolor; //描画色 | ||
int state; //内部状態 | int state; //内部状態 | ||
| − | int sXXX; // | + | int sXXX; //自分と両隣りの状態 000-111(0-7)の8通り |
public: | public: | ||
| 65行: | 87行: | ||
}; | }; | ||
</pre> | </pre> | ||
| + | |||
| + | |||
;Cell.cpp | ;Cell.cpp | ||
| + | *ルール90(01011010)の規則を記述 | ||
<pre> | <pre> | ||
#include "Cell.h" | #include "Cell.h" | ||
Cell::Cell(){ | Cell::Cell(){ | ||
| − | |||
width = 4; | width = 4; | ||
| − | + | bcolor = ofColor(255, 0, 0); | |
| − | bcolor = ofColor(255, 0, 0 | + | |
} | } | ||
void Cell::update(){ | void Cell::update(){ | ||
| + | //自分と両隣りの状態に応じて次の自分の状態を決める | ||
switch(sXXX){ | switch(sXXX){ | ||
case 0: //000 | case 0: //000 | ||
| 115行: | 139行: | ||
;ofApp.h | ;ofApp.h | ||
| + | * クラスの配列cellを生成。その1の通常の配列cellとの違いに注意。 | ||
<pre> | <pre> | ||
#pragma once | #pragma once | ||
| 120行: | 145行: | ||
#include "ofMain.h" | #include "ofMain.h" | ||
#include "Cell.h" | #include "Cell.h" | ||
| − | |||
class ofApp : public ofBaseApp{ | class ofApp : public ofBaseApp{ | ||
| 164行: | 188行: | ||
int iP = (i - 1 + NUM ) % NUM; | int iP = (i - 1 + NUM ) % NUM; | ||
int iN = (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].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].update(); | ||
| − | cell[i][j].pos = ofPoint(i * cell[i][j].width, j * cell[i][j].width); | + | cell[i][j].pos = ofPoint(i * cell[i][j].width, j * cell[i][j].width); //セルの描画位置を指定 |
| − | + | ||
} | } | ||
} | } | ||
| 180行: | 204行: | ||
} | } | ||
} | } | ||
| + | } | ||
| + | </pre> | ||
| + | |||
| + | == 256種のルールのセルオートマトン == | ||
| + | * 256種類のルール全てのセルオートマトンを順番に表示する。 | ||
| + | |||
| + | ;Cell.h | ||
| + | <pre> | ||
| + | #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(); | ||
| + | }; | ||
| + | </pre> | ||
| + | |||
| + | ;Cell.cpp | ||
| + | <pre> | ||
| + | #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); | ||
| + | } | ||
| + | } | ||
| + | </pre> | ||
| + | |||
| + | ;10進数から2進数の変換 | ||
| + | :10進数 n を2進数に変換した時の2^kの位の値は ( n % 2^(k+1) ) / 2^k で表せる。 | ||
| + | |||
| + | ;ofApp.h | ||
| + | <pre> | ||
| + | #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進値 | ||
| + | }; | ||
| + | </pre> | ||
| + | |||
| + | ;ofApp.cpp | ||
| + | <pre> | ||
| + | #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); | ||
} | } | ||
</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);
}