Processing:Примеры/Клеточный автомат Вольфрама
Материал из Онлайн справочника
Перейти к навигацииПерейти к поиску
Содержание | Среда разработки Processing | Справочник языка Processing | Библиотеки | Примеры | Режимы программирования |
Перевод: Максим Кузьмин
Проверка/Оформление/Редактирование: Мякишев Е.А.
Описание[1]
Простая демонстрация одномерного клеточного автомата Вольфрама. Достигнув нижней части экрана, система перезапускается с новым набором правил. Кроме того, перезапустить систему можно при помощи клика мышкой.
Пример
CA ca; // объект для описания
// простого клеточного автомата Вольфрама
void setup() {
size(640, 360);
int[] ruleset = {0,1,0,1,1,0,1,0}; // начальный набор правил
ca = new CA(ruleset); // инициализируем CA
background(0);
}
void draw() {
ca.render(); // рисуем CA
ca.generate(); // генерируем новый уровень
if (ca.finished()) { // если закончили, очищаем экран,
// берем новый набор правил и перезапускаем
background(0);
ca.randomize();
ca.restart();
}
}
void mousePressed() {
background(0);
ca.randomize();
ca.restart();
}
class CA {
int[] cells; // массив, состоящий из «0» и «1»
int generation; // как много поколений?
int scl; // какова высота/ширина каждой клетки (в пикселях)?
int[] rules; // массив для хранения набора правил;
// например, {0,1,1,0,1,1,0,1}
CA(int[] r) {
rules = r;
scl = 1;
cells = new int[width/scl];
restart();
}
// задаем правила для CA:
void setRules(int[] r) {
rules = r;
}
// создаем случайный набор правил:
void randomize() {
for (int i = 0; i < 8; i++) {
rules[i] = int(random(2));
}
}
// сбрасываем поколение до 0:
void restart() {
for (int i = 0; i < cells.length; i++) {
cells[i] = 0;
}
cells[cells.length/2] = 1; // начинаем с клетки,
// находящейся посередине экрана
// и имеющей состояние «1»
generation = 0;
}
// процесс создания нового поколения:
void generate() {
// сначала создаем пустой массив для новых значений:
int[] nextgen = new int[cells.length];
// задаем новое состояние для каждой точки
// на основе ее текущего состояния и состояния «соседей»;
// (игнорируем края, где у пикселей только один «сосед»):
for (int i = 1; i < cells.length-1; i++) {
int left = cells[i-1]; // состояние соседа «слева»
int me = cells[i]; // текущее состояние
int right = cells[i+1]; // состояние соседа «справа»
// рассчитываем следующее поколение на основе набора правил:
nextgen[i] = executeRules(left,me,right);
}
// копируем массив «nextgen» в массив «cells»:
for (int i = 1; i < cells.length-1; i++) {
cells[i] = nextgen[i];
}
//cells = (int[]) nextgen.clone();
generation++;
}
// здесь ничего сложного; просто рисуем клетки:
// цветовое значение «255» для «1», «0» для «0»:
void render() {
for (int i = 0; i < cells.length; i++) {
if (cells[i] == 1) {
fill(255);
} else {
fill(0);
}
noStroke();
rect(i*scl,generation*scl, scl,scl);
}
}
// реализовываем правила Вольфрама;
// это можно сделать более лаконично,
// но этот способ наглядно объясняет, что мы делаем в каждом случае:
int executeRules (int a, int b, int c) {
if (a == 1 && b == 1 && c == 1) { return rules[0]; }
if (a == 1 && b == 1 && c == 0) { return rules[1]; }
if (a == 1 && b == 0 && c == 1) { return rules[2]; }
if (a == 1 && b == 0 && c == 0) { return rules[3]; }
if (a == 0 && b == 1 && c == 1) { return rules[4]; }
if (a == 0 && b == 1 && c == 0) { return rules[5]; }
if (a == 0 && b == 0 && c == 1) { return rules[6]; }
if (a == 0 && b == 0 && c == 0) { return rules[7]; }
return 0;
}
// если CA достиг нижней части экрана, значит, он закончен:
boolean finished() {
if (generation > height/scl) {
return true;
} else {
return false;
}
}
}
См.также
Внешние ссылки
Примеры на Processing | |
---|---|
Основы |
|
Продвинутые графические эффекты |
|
Примеры из сторонних библиотек |