相信不少接触过C语言编成的同学都了解过“生命细胞机”这么一个有意思的游戏。这个游戏由英国数学家约翰·何顿·康威在1970年发明。上图所示即为生命细胞机一个非常经典的结构:“播种者”,他有很多个高斯帕滑翔机枪组成并且一直平移,所经过之处会产生许多个高斯帕滑翔机枪不断生成高斯帕滑翔机。
生命游戏中,对于任意细胞,规则如下:
- 每个细胞有两种状态 - 存活或死亡,每个细胞与以自身为中心的周围八格细胞产生互动
- 当前细胞为存活状态时,当周围的存活细胞低于2个时(不包含2个),该细胞变成死亡状态。(模拟生命数量稀少)
- 当前细胞为存活状态时,当周围有2个或3个存活细胞时,该细胞保持原样。
- 当前细胞为存活状态时,当周围有超过3个存活细胞时,该细胞变成死亡状态。(模拟生命数量过多)
- 当前细胞为死亡状态时,当周围有3个存活细胞时,该细胞变成存活状态。(模拟繁殖)
可以把最初的细胞结构定义为种子,当所有在种子中的细胞同时被以上规则处理后,可以得到第一代细胞图。按规则继续处理当前的细胞图,可以得到下一代的细胞图,周而复始。
下面给出生命游戏中几种经典的细胞形态:
怎么使用C语言实现生命细胞机呢?
其实生命细胞机的规则很简单,我们首先需要初始化一个二位数组模拟“棋盘”布局。随后我们生成一定量的初始点,并且使用循环的方式遍历这个数组所有的点,依次判断他们周边点的状态,从而确定下一次周期该点的生存或者死亡。
我们先给出实现代码:
#include<stdio.h>
#include <unistd.h>
#include<time.h>
#include<memory.h>
#include<string>
#include <cstdlib>
using namespace std;
int life[80][240] = {0};//生命矩阵
int lifen[80][240]= {0};//中间矩阵
int mm, nn,s,times=0;
int main(){
srand((unsigned)time(NULL));
for (int sy = 0; sy < 80; sy++) { //全部点都初始化为活
for (int s = 0; s < 240; s++) {
life[sy][s] =1;
lifen[sy][s] = 1;
}
}
/*这里可以生成随机的生命点
for (int ra = 0; ra < 800; ra++) {
mm = (rand()%80);
nn= (rand() % 240);
life[mm][nn] = 1;
lifen[mm][nn] = 1;
}*/
int m,t,e;
while(1){
for(int y=1;y<79;y++)
{//对所有的数据点进行遍历
for(int x=1;x<239;x++)
{
if(life[y][x]==1)
{
m=0;
m = life[y - 1][x - 1] + life[y - 1][x] + life[y - 1][x + 1] + life[y][x - 1] + life[y][x + 1] + life[y + 1][x - 1] + life[y + 1][x + 1] + life[y + 1][x];//统计周围点的生存状态
if(m==2){
lifen[y][x]=1;
}
else if(m==3){
lifen[y][x]=1;
}
else lifen[y][x]=0;
}
if (life[y][x] == 0)
{
m = 0;
m = life[y - 1][x - 1] + life[y - 1][x] + life[y - 1][x + 1] + life[y][x - 1] + life[y][x + 1] + life[y + 1][x - 1] + life[y + 1][x +1] + life[y + 1][x];
if (m == 3) {
lifen[y][x] = 1;
}
else lifen[y][x] = 0;
}
}
}
for(int my=0;my<80;my++)
{
for(int mx=0;mx<240;mx++)
{
life[my][mx]=lifen[my][mx];//将中间的矩阵状态复制给生命矩阵
}
}
printf("start print:%d\n",times);
for (int py = 0; py < 80; py++)
{
for (int px = 0; px < 240; px++)
{
if (life[py][px] == 0) {
printf("\033[47m*\033[0m");//点死亡为白色
}
else {
printf("\033[41m*\033[0m");//点存活为红色
}
}
printf("\n");
}
usleep(100000);//每一次刷新停留0.1秒
system("clear");
times++;
}
}
这段代码的执行效果如图:
程序在执行一段时间后会到达稳态,如图所示:
高斯帕滑翔机枪
那么实现了生命细胞机的基本结构,我们怎么生成震撼的滑翔机呢?
这就要求我们具有恰当的初始化的种子,这需要符合高斯帕滑翔机枪的初始结构,在这里我把它们初始化为这些点:
for (int sy = 2; sy < 11; sy++) {
for (int ss = 0; ss < 240; ss++) {
s=ss/40;
s=s*40;
if(sy==2){life[sy][s+4]=1;life[sy][s+10]=1;life[sy][s+11]=1;}
else if(sy==3){life[sy][s+2]=1;life[sy][s+6]=1;life[sy][s+10]=1;life[sy][s+11]=1;life[sy][s+12]=1;}
else if(sy==4){life[sy][s+6]=1;life[sy][s+12]=1;life[sy][s+13]=1;life[sy][s+15]=1;life[sy][s+24]=1;}
else if(sy==5){life[sy][s+1]=1;life[sy][s+7]=1;life[sy][s+12]=1;life[sy][s+15]=1;life[sy][s+22]=1;life[sy][s+24]=1;}
else if(sy==6){life[sy][s+1]=1;life[sy][s+2]=1;life[sy][s+12]=1;life[sy][s+13]=1;life[sy][s+15]=1;life[sy][s+21]=1;life[sy][s+23]=1;}
else if(sy==7){life[sy][s+10]=1;life[sy][s+11]=1;life[sy][s+12]=1;life[sy][s+20]=1;life[sy][s+23]=1;life[sy][s+35]=1;life[sy][s+36]=1;}
else if(sy==8){life[sy][s+10]=1;life[sy][s+11]=1;life[sy][s+21]=1;life[sy][s+23]=1;life[sy][s+35]=1;life[sy][s+36]=1;}
else if(sy==9){life[sy][s+22]=1;life[sy][s+24]=1;}
else if(sy==10){life[sy][s+24]=1;}
}
}
接下来给出完整代码:
#include<stdio.h>
#include <unistd.h>
#include<time.h>
#include<memory.h>
#include<string>
#include <cstdlib>
using namespace std;
int life[80][240] = {0};
int lifen[80][240]= {0};
int mm, nn,s,times=0;
int main(){
for (int sj = 0; sj < 80; sj++) {
for (int sm = 0; sm < 240; sm++) {
life[sj][sm] =0;
lifen[sj][sm] = 0;
}
}
for (int sy = 2; sy < 11; sy++) {
for (int ss = 0; ss < 240; ss++) {
s=ss/40;
s=s*40;
if(sy==2){life[sy][s+4]=1;life[sy][s+10]=1;life[sy][s+11]=1;}
else if(sy==3){life[sy][s+2]=1;life[sy][s+6]=1;life[sy][s+10]=1;life[sy][s+11]=1;life[sy][s+12]=1;}
else if(sy==4){life[sy][s+6]=1;life[sy][s+12]=1;life[sy][s+13]=1;life[sy][s+15]=1;life[sy][s+24]=1;}
else if(sy==5){life[sy][s+1]=1;life[sy][s+7]=1;life[sy][s+12]=1;life[sy][s+15]=1;life[sy][s+22]=1;life[sy][s+24]=1;}
else if(sy==6){life[sy][s+1]=1;life[sy][s+2]=1;life[sy][s+12]=1;life[sy][s+13]=1;life[sy][s+15]=1;life[sy][s+21]=1;life[sy][s+23]=1;}
else if(sy==7){life[sy][s+10]=1;life[sy][s+11]=1;life[sy][s+12]=1;life[sy][s+20]=1;life[sy][s+23]=1;life[sy][s+35]=1;life[sy][s+36]=1;}
else if(sy==8){life[sy][s+10]=1;life[sy][s+11]=1;life[sy][s+21]=1;life[sy][s+23]=1;life[sy][s+35]=1;life[sy][s+36]=1;}
else if(sy==9){life[sy][s+22]=1;life[sy][s+24]=1;}
else if(sy==10){life[sy][s+24]=1;}
}
}
int m,t,e;
while(1){
for(int y=1;y<79;y++)
{
for(int x=1;x<239;x++)
{
if(life[y][x]==1)
{
m=0;
m = life[y - 1][x - 1] + life[y - 1][x] + life[y - 1][x + 1] + life[y][x - 1] + life[y][x + 1] + life[y + 1][x - 1] + life[y + 1][x + 1] + life[y + 1][x];
if(m==2){
lifen[y][x]=1;
}
else if(m==3){
lifen[y][x]=1;
}
else lifen[y][x]=0;
}
if (life[y][x] == 0)
{
m = 0;
m = life[y - 1][x - 1] + life[y - 1][x] + life[y - 1][x + 1] + life[y][x - 1] + life[y][x + 1] + life[y + 1][x - 1] + life[y + 1][x +1] + life[y + 1][x];
if (m == 3) {
lifen[y][x] = 1;
}
else lifen[y][x] = 0;
}
}
}
for(int my=0;my<80;my++)
{
for(int mx=0;mx<240;mx++)
{
life[my][mx]=lifen[my][mx];
}
}
//if (times %==1) {
printf("start print:%d\n",times);
for (int py = 0; py < 80; py++)
{
for (int px = 0; px < 240; px++)
{
if (life[py][px] == 0) {
//color(7);
printf("\033[47m*\033[0m");
//color(1);
}
else {
//color(1);
printf("\033[41m*\033[0m");
//color(7);
}
}
printf("\n");
}
usleep(100000);
system("clear");
//}
times++;
}
}
运行结果:
模拟细胞分裂
如果我们对康威的生命规则进行一些改变:
- 生命不会凭空产生,旧的生命可以制造新的生命。
- 由于环境绕动,生命可能发生位置上的移动。
- 生命会在一定的周期后消亡,并且生命害怕拥挤
- 生命不害怕孤独。
那么根据上面的规则我们修改代码如下:
#include<stdio.h>
#include <unistd.h>
#include<time.h>
#include<memory.h>
#include<string>
#include <cstdlib>
using namespace std;
int life[80][400];
int lifen[80][400];
int lifes[80][400];
int period[80][400];
int mm, nn,s,times=0,ry,rx;
int main(){
for (int sj = 0; sj < 80; sj++) {//初始化所有生命为死亡
for (int sm = 0; sm < 400; sm++) {
life[sj][sm] =0;
lifen[sj][sm] = 0;
lifes[sj][sm] = 0;
period[80][400];
}
}
life[40][120]=1;period[40][120]=5;lifes[40][120]=1;//再一个点初始化一个生命
srand((unsigned)time(NULL));
int m,t,e;
while(1){
if(life[ry=rand()%80][rx=rand()%400]==1){//生命会随机的发生位移
life[ry][rx]==0;
life[ry=rand()%80][rx=rand()%400]=1;period[ry][rx]=5;lifes[ry][rx]=1;
}
for(int y=1;y<79;y++)
{//开始遍历数组
for(int x=1;x<399;x++)
{
if(life[y][x]==1)
{
m=0;
m = life[y - 1][x - 1] + life[y - 1][x] + life[y - 1][x + 1] + life[y][x - 1] + life[y][x + 1] + life[y + 1][x - 1] + life[y + 1][x + 1] + life[y + 1][x];
if(m==0){
lifen[y][x]=1;
}
else if(m==1){
lifen[y][x]=1;
}
else if(m==2){
lifen[y][x]=1;
}
else {lifen[y][x]=0;period[y][x]==0;}
if(period[y][x]!=0)
period[y][x]=period[y][x]-1;//生命周期减少
else if(period[y][x]==0)lifen[y][x] = 0;
}
else if (life[y][x] == 0)
{
m = 0;
mm=(rand()%2);
if(mm==1){
m = lifes[y - 1][x - 1] + lifes[y - 1][x] + lifes[y - 1][x + 1] + lifes[y][x - 1] + lifes[y][x + 1] + lifes[y + 1][x - 1] + lifes[y + 1][x +1] + lifes[y + 1][x];
if(lifes[y - 1][x - 1]==1)lifes[y - 1][x - 1]=0;
else if(lifes[y - 1][x]==1)lifes[y - 1][x]=0;
else if(lifes[y - 1][x+1]==1)lifes[y - 1][x+1]=0;
else if(lifes[y][x-1]==1)lifes[y][x-1]=0;
else if(lifes[y][x+1]==1)lifes[y][x+1]=0;
else if(lifes[y+1][x-1]==1)lifes[y + 1][x-1]=0;
else if(lifes[y+1][x]==1)lifes[y + 1][x]=0;
else if(lifes[y+1][x+1]==1)lifes[y + 1][x+1]=0;
}
if (m != 0) {
lifen[y][x] = 1;period[y][x]=5;//新生命诞生,初始化生命周期
}
else {lifen[y][x]=0;period[y][x]==0;}
}
}
}
for(int my=0;my<80;my++)
{
for(int mx=0;mx<400;mx++)
{
life[my][mx]=lifen[my][mx];
lifes[my][mx]=lifen[my][mx];
}
}
printf("start print:%d\n",times);
for (int py = 0; py < 80; py++)
{
for (int px = 0; px < 400; px++)
{
if (life[py][px] == 0) {
printf("\033[47m*\033[0m");
}
else {
printf("\033[41m*\033[0m");
}
}
printf("\n");
}
usleep(300000);
system("clear");
times++;
}
}
最后来看看效果图吧: