1次元セルオートマトン

提供:kuhalaboWiki
(版間での差分)
移動: 案内, 検索
(Wolframのセルオートマトン)
 
(1人の利用者による、間の38版が非表示)
1行: 1行:
== Wolframのセルオートマトン ==
+
== openFrameworksのサンプル ==
  
シェルピンスキーのガスケットの描画
+
Wolframのセルオートマトンの描画プログラム
  
 +
== シンプルに配列だけで記述 ==
 +
=== シェルピンスキーのギャスケット その1 ===
 +
* 2次元配列cell[256][256]を作り、まとめて状態を更新し、描画する。
 
<pre>
 
<pre>
 
#include "ofApp.h"
 
#include "ofApp.h"
11行: 14行:
 
//--------------------------------------------------------------
 
//--------------------------------------------------------------
 
void ofApp::setup(){
 
void ofApp::setup(){
 
+
ofBackground(0, 0, 0); //背景色の設定
 
//初期状態は真ん中だけが 1 で残りはすべて 0
 
//初期状態は真ん中だけが 1 で残りはすべて 0
 
for(int i = 0; i < NUM; i++){
 
for(int i = 0; i < NUM; i++){
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; //状態遷移則 %は剰余演算
 
}
 
}
 
}
 
}
39行: 42行:
 
}
 
}
 
}
 
}
 +
}
 +
</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クラスを設計
 +
<pre>
 +
#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();
 +
};
 +
</pre>
 +
 +
 +
 +
;Cell.cpp
 +
*ルール90(01011010)の規則を記述
 +
<pre>
 +
#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);
 +
}
 +
}
 +
</pre>
 +
 +
;ofApp.h
 +
* クラスの配列cellを生成。その1の通常の配列cellとの違いに注意。
 +
<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];
 +
 +
};
 +
</pre>
 +
 +
;ofApp.cpp
 +
<pre>
 +
//--------------------------------------------------------------
 +
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();
 +
}
 +
}
 +
}
 +
</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);
}

[編集] 参考

ジェネラティブアート論

個人用ツール
名前空間

変種
操作
案内
ツールボックス