实现一个简单的元胞自动机,可以自定义初始状态、运行规则。以此基础实现一个能自动绘制大量万花筒图像的程序。
注:为了防止二维数组输出时画面闪烁,采取双屏幕缓冲区轮流显示。将缓冲区写好后一次性输出可以防止数组循环输出方式会导致的画面闪烁。
#include
#include
#include
#include
#include
#include
#include
#define BLACK 0
#define WHITE 15
#define GREEN 10
#define YELLOW 14
#define RED 12
#define BLUE 9
#define CYAN 11
#define PURPLE 13
#define INCI(x) (((x)+1)%(COL))
#define DECI(x) (((x)+COL-1)%(COL))
#define INCJ(x) (((x)+1)%(RAW))
#define DECJ(x) (((x)+RAW-1)%(RAW))
#define MODE "mode 82,42"
#define COL 41
#define RAW 41
using namespace std;
int ct=0;
HANDLE hOutput, hOutBuf;//控制台屏幕缓冲区句柄
COORD coord={0,0};
WORD att;
DWORD bytes=0;
char data[COL][RAW];
int clr[8]={BLACK,WHITE,GREEN,YELLOW,RED,BLUE,CYAN,PURPLE};
int a[COL][RAW]={0},b[COL][RAW]={0};
unsigned int counts=0;
char str[11];
void f0()//规则0:空心万花筒
{
int i,j,k;
memset(b,0,sizeof(b));
for(i=0;i<COL;i++)
for(j=0;j<RAW;j++)
{
k=a[i][j];
b[(i+rand()%3-1)%COL][(j+rand()%3-1)%RAW]+=k;
b[(i+rand()%3-1)%COL][(j+rand()%3-1)%RAW]+=k;
}
for(i=0;i<COL;i++)
for(j=0;j<RAW;j++)
{
a[i][j]=b[i][j]%8;
}
}
void f1()//规则1:万花筒
{
int i,j,k;
memset(b,0,sizeof(b));
for(i=0;i<COL;i++)
for(j=0;j<RAW;j++)
{
k=a[i][j];
//b[i][j]+=k;
b[DECI(i)][j]+=k;
b[INCI(i)][j]+=k;
b[i][DECJ(j)]+=k;
b[i][INCJ(j)]+=k;
}
for(i=0;i<COL;i++)
for(j=0;j<RAW;j++)
{
a[i][j]=b[i][j]%8;
}
}
void f2p()//滑翔机初始化
{
a[1][5]=1;
a[2][5]=1;
a[1][6]=1;
a[2][6]=1;
a[11][5]=1;
a[11][6]=1;
a[11][7]=1;
a[12][4]=1;
a[12][8]=1;
a[13][3]=1;
a[13][9]=1;
a[14][3]=1;
a[14][9]=1;
a[15][6]=1;
a[16][4]=1;
a[16][8]=1;
a[17][5]=1;
a[17][6]=1;
a[17][7]=1;
a[18][6]=1;
a[21][3]=1;
a[21][4]=1;
a[21][5]=1;
a[22][3]=1;
a[22][4]=1;
a[22][5]=1;
a[23][2]=1;
a[23][6]=1;
a[25][1]=1;
a[25][2]=1;
a[25][6]=1;
a[25][7]=1;
a[35][3]=1;
a[35][4]=1;
a[36][3]=1;
a[36][4]=1;
}
void f2()//规则2:生命游戏
{
int i,j,k;
memset(b,0,sizeof(b));
for(i=0;i<COL;i++)
for(j=0;j<RAW;j++)
{
k=0;
if(a[DECI(i)][j])k++;
if(a[INCI(i)][j])k++;
if(a[i][DECJ(j)])k++;
if(a[i][INCJ(j)])k++;
if(a[DECI(i)][DECJ(j)])k++;
if(a[DECI(i)][INCJ(j)])k++;
if(a[INCI(i)][DECJ(j)])k++;
if(a[INCI(i)][INCJ(j)])k++;
if(k==3)b[i][j]=1;
else if(k==2)b[i][j]=a[i][j];
else b[i][j]=0;
}
for(i=0;i<COL;i++)
for(j=0;j<RAW;j++)
{
a[i][j]=b[i][j];
}
}
void show()//显示
{
int i,j;
for(i=0;i<COL;i++)
{
for(j=0;j<RAW;j++)
{
coord.X=2*i;
coord.Y=j;
att=clr[a[i][j]];
if(a[i][j])
{
WriteConsoleOutputCharacterA(hOutBuf,"■",2,coord,&bytes);
}
else WriteConsoleOutputCharacterA(hOutBuf," ",2,coord,&bytes);
WriteConsoleOutputAttribute(hOutBuf,&att,1,coord,&bytes);
coord.X++;
WriteConsoleOutputAttribute(hOutBuf,&att,1,coord,&bytes);
}
}
itoa(counts,str,10);
coord.X=0;coord.Y=41;
WriteConsoleOutputCharacterA(hOutBuf,str,sizeof(str),coord,&bytes);
att=WHITE;
WriteConsoleOutputAttribute(hOutBuf,&att,1,coord,&bytes);
SetConsoleActiveScreenBuffer(hOutBuf);
f1();//规则替换处
//Sleep(50);
getch();//任意键继续
counts++;
for(i=0;i<COL;i++)
{
for(j=0;j<RAW;j++)
{
coord.X=2*i;
coord.Y=j;
att=clr[a[i][j]];
if(a[i][j])
{
WriteConsoleOutputCharacterA(hOutput,"■",2,coord,&bytes);
}
else WriteConsoleOutputCharacterA(hOutput," ",2,coord,&bytes);
WriteConsoleOutputAttribute(hOutput,&att,1,coord,&bytes);
coord.X++;
WriteConsoleOutputAttribute(hOutput,&att,1,coord,&bytes);
}
}
itoa(counts,str,10);
coord.X=0;coord.Y=41;
WriteConsoleOutputCharacterA(hOutput,str,sizeof(str),coord,&bytes);
att=WHITE;
WriteConsoleOutputAttribute(hOutput,&att,1,coord,&bytes);
SetConsoleActiveScreenBuffer(hOutput);
f1();//规则替换处
//Sleep(50);
getch();counts++;
}
int main()
{
srand(time(NULL));
system(MODE);
hOutBuf = CreateConsoleScreenBuffer(
GENERIC_WRITE,
FILE_SHARE_WRITE,
NULL,
CONSOLE_TEXTMODE_BUFFER,
NULL
);
hOutput = CreateConsoleScreenBuffer(
GENERIC_WRITE,
FILE_SHARE_WRITE,
NULL,
CONSOLE_TEXTMODE_BUFFER,
NULL
);
CONSOLE_CURSOR_INFO cci;
cci.bVisible = 0;
cci.dwSize = 1;
SetConsoleCursorInfo(hOutput, &cci);
SetConsoleCursorInfo(hOutBuf, &cci);
a[COL/2][RAW/2]=1;
//a[rand()%COL][rand()%RAW]=1;
//f2p();
while(1)show();
}