粗略的理解元胞自动机:
元胞可以看做一个的基本单位,就好比培养皿中的一个细胞。这个细胞有两个状态:生和死
假设一个元胞可以通过吞噬周围一定范围内的细胞来延长自身的生命。那么显然,这个元胞的下一个时刻的状态取决于前一个状态以及下一个位置周围的细胞的状态。假设某一时刻元胞状态变化到下一个时刻的状态记为:s[t] -> s[t+1]
一个元胞的周围固定范围内,某一个时刻的活元胞数量为:n[t] = sum(s[ti],i=1,2...n),n取决于范围大小
如果规定:
- 元胞可触及范围为8,即其周围的8个元胞
- 当一个元胞周围活元胞数量等于2时,下一个状态与当前状态相同
- 当一个元胞周围活元胞数量等于3时,则此元胞为生
- 其他情况为死
那么,就构成了一个简易的元胞自动机。
matlab实现:
1.初始化元胞状态(区域为60x60的正方形,元胞初始化为生的概率为0.25):
m=60;n=60;p=.75;h=200;
%{
m,n为元胞集合的区域
p为生成元胞为死的概率
h为元胞的迭代次数
%}
for x=1:m
for y=1:n
r=rand(1);
if r>p
a(x,y)=1;
else a(x,y)=0;
end
end
end
2.绘制初始化后的元胞图(单个元胞用1x1填充方格表示):
for x=1:m
for y=1:n
if a(x,y)==1
fx=[x-1,x-1,x,x];fy=[y-1,y,y,y-1];fill(fx,fy,'g'),hold on;
end
end
end
3.迭代元胞,模拟细胞的消亡、吞噬、分裂
for k=1:h %迭代次数
fx=[0,m,m,0];fy=[0,0,n,n];fill(fx,fy,'k'),hold on
for x=2:m-1
for y=2:n-1
%统计元胞周围的活元胞
b(x,y)=a(x-1,y-1)+a(x-1,y)+a(x-1,y+1)+a(x,y-1)+a(x,y+1)+a(x+1,y-1)+a(x+1,y)+a(x+1,y+1);
if b(x,y)==2,c(x,y)=a(x,y);
elseif b(x,y)==3,c(x,y)=1;
else c(x,y)=0;
end
end
end
%边界的处理
c(1:m,1)=a(1:m,1);c(1:m,n)=a(1:m,n);
for x=1:m
for y=1:n
if c(x,y)==1
%绘制活细胞
fx=[x-1,x-1,x,x];fy=[y-1,y,y,y-1];fill(fx,fy,'g'),hold on
end
end
end
pause(.005)
%将每次迭代的结果作为下一次迭代的开始
a=c;
效果:
C++&easyx实现:
1.Cell.h
#pragma once
#ifndef _initCells_
#define _initCells_
#include <iostream>
#include "Cells.h"
#include <graphics.h>
#include <conio.h>
using namespace std;
class Cell
{
public:
Cell();
Cell(double p);
~Cell();
void initCellGraphics();
void closeCellGraphics();
void PaintCells();
void CellLife();
private:
int cell[23][31] = { 0 };
};
Cell::Cell()
{
for (int i = 0; i < 23; i++) {
for (int j = 0; j < 31; j++) {
if ((rand() % 100) > 85) {
cell[i][j] = 1;
}
else {
cell[i][j] = 0;
}
}
}
}
inline Cell::Cell(double p)
{
for (int i = 0; i < 23; i++) {
for (int j = 0; j < 31; j++) {
if ((rand() % 100) > p) {
this->cell[i][j] = 1;
}
else {
this->cell[i][j] = 0;
}
}
}
}
Cell::~Cell()
{
}
inline void Cell::initCellGraphics()
{
initgraph(640, 480);
setbkcolor(WHITE);
cleardevice();
setlinecolor(BLACK);
rectangle(5, 5, 635, 475);
setlinecolor(RGB(184, 105, 59));
for (int i = 0; i < 23; i++) {
for (int j = 0; j < 31; j++) {
rectangle(10 + j * 20, 10 + i * 20, 30 + j * 20, 30 + i * 20);
}
}
}
inline void Cell::closeCellGraphics()
{
closegraph();
}
inline void Cell::PaintCells()
{
for (int i = 0; i < 23; i++){
for (int j = 0; j < 31; j++){
if (this->cell[i][j] == 1) {
setfillcolor(RGB(226, 42, 45));
fillrectangle(10 + j * 20, 10 + i * 20, 30 + j * 20, 30 + i * 20);
}
else {
setfillcolor(RGB(255, 255, 255));
fillrectangle(10 + j * 20, 10 + i * 20, 30 + j * 20, 30 + i * 20);
}
}
}
}
inline void Cell::CellLife()
{
for (int i = 1; i < 22; i++) {
for (int j = 1; j < 30; j++) {
int count = this->cell[i - 1][j - 1] + this->cell[i - 1][j] + this->cell[i - 1][j + 1];
count += this->cell[i + 1][j - 1] + this->cell[i + 1][j] + this->cell[i + 1][j + 1];
count += this->cell[i][j - 1] + this->cell[i][j + 1];
if (count == 3) {
this->cell[i][j] = 1;
}
else if (count == 2) {
this->cell[i][j] = this->cell[i][j];
}
else {
this->cell[i][j] = 0;
}
}
}
}
#endif // !_initCells_
2.main.cpp
#include <iostream>
#include <graphics.h>
#include <conio.h>
#include "Cells.h"
using namespace std;
int main() {
Cell cs;
cs.initCellGraphics();
int a = 0;
while (a++ < 200) {
cs.PaintCells();
cs.CellLife();
Sleep(500);
}
cs.closeCellGraphics();
return 0;
}
效果: