matlab/C++ :元胞自动机实现生命游戏

粗略的理解元胞自动机:

元胞可以看做一个的基本单位,就好比培养皿中的一个细胞。这个细胞有两个状态:生和死

假设一个元胞可以通过吞噬周围一定范围内的细胞来延长自身的生命。那么显然,这个元胞的下一个时刻的状态取决于前一个状态以及下一个位置周围的细胞的状态。假设某一时刻元胞状态变化到下一个时刻的状态记为: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;
}

效果:

  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

尼卡尼卡尼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值