////////////////////////////////////////////////////////////////////////////////
//
// 生命游戏
// 由剑桥大学的 John Horton Conway 发明的。
// 它在一个由方格组成的 M * N 的矩形上进行,
// 我们用 occ(k) 表示与方格 k 相邻的、被有机体所占有的方格数。
// 机体分布每隔一定时间变化一次,
// 有的死亡,有的产生新的机体。
// 从某一种机体分布情况到新生成的机体分布情况应满足下述二个规则:
// 1. 若 2 <= occ(k) <= 3 , 则方格 k 中的机体仍活到下一次生成(若 k 非空),否则死亡。
// 2. 若 occ(k) == 3 , 则在空方格 k 中生成一个新的机体。
// 程序功能: 模拟机体分布,及其变化
// 程序员: 黄江斌 http://blog.youkuaiyun.com/zerodspace
// 时间: 14:25 2005-11-20
// 调试平台: Microsoft VC++6.0
//
////////////////////////////////////////////////////////////////////////////////
#include "windows.h"
#include "assert.h"
#include "limits.h"
#include "conio.h"
#include "time.h"
#include "fstream.h"
#ifdef _DEBUG
#define verify(f) assert(f)
#else
#define verify(f) ((void)(f))
#endif
class Console // 控制台
{
friend class Window;
public:
// title: 控制台标题
// point: 控制台宽度和高度
void Open( const char* title, COORD wl )
{
assert( wl.X>0 && wl.Y>0 );
verify( (hStdOutput=GetStdHandle(STD_OUTPUT_HANDLE)) != INVALID_HANDLE_VALUE ); // 获得输出句柄
verify( SetConsoleTitle( title ) ); // 设置标题
CONSOLE_CURSOR_INFO cci = { 25, FALSE };
verify( SetConsoleCursorInfo( hStdOutput, &cci ) ); // 去除光标
SMALL_RECT wrt = { 0, 0, wl.X-1, wl.Y-1 };
verify( SetConsoleWindowInfo( hStdOutput, TRUE, &wrt ) ); // 设置窗体尺寸
coord = wl;
verify( SetConsoleScreenBufferSize( hStdOutput, coord ) ); // 设置缓冲尺寸
}
private:
HANDLE hStdOutput;
COORD coord;
};
class Window // 窗体是控制台的一个子部分
{
public:
// wrect: 窗体左上角坐标,右下角坐标
void Open( Console& console, SMALL_RECT wrect )
{
assert( wrect.Left < wrect.Right && wrect.Top < wrect.Bottom );
assert( wrect.Left>=0 && wrect.Right<=console.coord.X );
assert( wrect.Top>=0 && wrect.Bottom<=console.coord.Y );
pcon = &console;
wrt = wrect;
}
// x,y: 相对于窗体的坐标
// color: 字体和背景颜色
// str: 欲输出字符串,遇0或达到len数量则结束,没考虑控制字符,比如/r等
void Output( short x, short y, WORD color, const char* str, size_t len=INT_MAX )
{
assert( x>=0 );
assert( x<=wrt.Right-wrt.Left );
assert( y>=0 );
assert( y<=wrt.Bottom-wrt.Top );
COORD c = { wrt.Left+x, wrt.Top+y };
DWORD n = 0;
WORD cs[2] = { color, color };
for( const char* p=str; len!=0 && *p!=0; --len,++p,++c.X )
{
if( c.X >= wrt.Right ) // 换行
{
c.X = wrt.Left+x;
++c.Y;
assert( c.Y < wrt.Bottom );
}
if( *p > 0 ) // 单字节字符
{
verify( WriteConsoleOutputCharacter( pcon->hStdOutput, p, 1, c, &n ) && n==1 );
verify( WriteConsoleOutputAttribute( pcon->hStdOutput, cs, 1, c, &n ) && n==1 );
}
else // 双字节字符
{
assert( len>=2 && *(p+1)!=0 && (c.X+1)hStdOutput, p, 2, c, &n ) && n==2 );
verify( WriteConsoleOutputAttribute( pcon->hStdOutput, cs, 2, c, &n ) && n==2 );
--len,++p,++c.X;
}
}
}
private:
Console* pcon;
SMALL_RECT wrt;
};
class Community
{
//构造函数、析构函数
public:
Community( Console &csl , COORD coord )
{
spaceX = (coord.X)/2;
spaceY = coord.Y;
distributing[0] = new int[spaceX*spaceY];
distributing[1] = new int[spaceX*spaceY];
occ[0] = new int[spaceX*spaceY];
occ[1] = new int[spaceX*spaceY];
currp = 0;
SMALL_RECT winrect = { 0 , 0 , coord.X , coord.Y };
win.Open( csl , winrect );
InitCommunity();
}
~Community()
{
delete[]distributing[0];
delete[]distributing[1];
delete[]occ[0];
delete[]occ[1];
}
//功能函数,公有
public:
//种群的初始化
void InitCommunity()
{
srand( (unsigned int)time(NULL) );
int i , j;
for( i = 0 ; i < spaceY ; i++ )
{
for( j = 0 ; j < spaceX ; j++ )
{
distributing[currp][i*spaceX+j] = rand() % 2;
}
}
computeOCC();
InitToFile();
}
//生成一下代种群
void GetNextGeneration()
{
int nextp = (currp+1)%2;
int i , j;
for( i = 0 ; i < spaceY ; i++ )
{
for( j = 0 ; j < spaceX ; j++ )
{
occ[nextp][i*spaceX+j] = occ[currp][i*spaceX+j]>0 ? occ[currp][i*spaceX+j] : 0 ;
}
}
for( i = 0 ; i < spaceY ; i++ )
{
for( j = 0 ; j < spaceX ; j++ )
{
if( occ[currp][i*spaceX+j] == 3 && distributing[currp][i*spaceX+j] == 0 )
{
distributing[nextp][i*spaceX+j] = 1;
//生成新的个体
if( i - 1 >= 0 )
occ[nextp][(i-1)*spaceX+j]++;
if( i + 1 < spaceY )
occ[nextp][(i+1)*spaceX+j]++;
if( j - 1 >= 0 )
occ[nextp][(i)*spaceX+j-1]++;
if( j + 1 < spaceX )
occ[nextp][(i)*spaceX+j+1]++;
if( i - 1 >= 0 && j - 1 >= 0 )
occ[nextp][(i-1)*spaceX+j-1]++;
if( i - 1 >= 0 && j + 1 < spaceX )
occ[nextp][(i-1)*spaceX+j+1]++;
if( i + 1 < spaceY && j - 1 >= 0 )
occ[nextp][(i+1)*spaceX+j-1]++;
if( i + 1 < spaceY && j + 1 < spaceX )
occ[nextp][(i+1)*spaceX+j+1]++;
}
else if( occ[currp][i*spaceX+j] != 2 && occ[currp][i*spaceX+j] != 3 && distributing[currp][i*spaceX+j] == 1 )
{
distributing[nextp][i*spaceX+j] = 0;
//个体死亡
if( i - 1 >= 0 )
occ[nextp][(i-1)*spaceX+j]--;
if( i + 1 < spaceY )
occ[nextp][(i+1)*spaceX+j]--;
if( j - 1 >= 0 )
occ[nextp][(i)*spaceX+j-1]--;
if( j + 1 < spaceX )
occ[nextp][(i)*spaceX+j+1]--;
if( i - 1 >= 0 && j - 1 >= 0 )
occ[nextp][(i-1)*spaceX+j-1]--;
if( i - 1 >= 0 && j + 1 < spaceX )
occ[nextp][(i-1)*spaceX+j+1]--;
if( i + 1 < spaceY && j - 1 >= 0 )
occ[nextp][(i+1)*spaceX+j-1]--;
if( i + 1 < spaceY && j + 1 < spaceX )
occ[nextp][(i+1)*spaceX+j+1]--;
}
else
{
distributing[nextp][i*spaceX+j] = distributing[currp][i*spaceX+j];
}
}
}
currp = nextp;
Display();
}
//功能函数,保护
protected:
void Display()
{
int i , j;
for( i = 0 ; i < spaceY ; i++ )
{
for( j = 0 ; j < spaceX ; j++ )
{
if( distributing[currp][spaceX*i+j] == 1 )
{
win.Output( 2*j , i , FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_INTENSITY , "■" , 2 );
}
else
{
win.Output( 2*j , i , FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_INTENSITY , "□" , 2 );
}
}
}
}
void computeOCC()
{
int i , j;
for( i = 0 ; i < spaceY ; i++ )
{
for( j = 0 ; j < spaceX ; j++ )
{
occ[currp][i*spaceX+j] = 0;
}
}
for( i = 0 ; i < spaceY ; i++ )
{
for( j = 0 ; j < spaceX ; j++ )
{
if( distributing[currp][i*spaceX+j] == 1 )
{
if( i - 1 >= 0 )
occ[currp][(i-1)*spaceX+j]++;
if( i + 1 < spaceY )
occ[currp][(i+1)*spaceX+j]++;
if( j - 1 >= 0 )
occ[currp][(i)*spaceX+j-1]++;
if( j + 1 < spaceX )
occ[currp][(i)*spaceX+j+1]++;
if( i - 1 >= 0 && j - 1 >= 0 )
occ[currp][(i-1)*spaceX+j-1]++;
if( i - 1 >= 0 && j + 1 < spaceX )
occ[currp][(i-1)*spaceX+j+1]++;
if( i + 1 < spaceY && j - 1 >= 0 )
occ[currp][(i+1)*spaceX+j-1]++;
if( i + 1 < spaceY && j + 1 < spaceX )
occ[currp][(i+1)*spaceX+j+1]++;
}
}
}
}
void InitToFile()
{
ofstream fout( "生命游戏.txt" );
int i , j;
for( i = 0 ; i < spaceY ; i++ )
{
for( j = 0 ; j < spaceX ; j++ )
{
fout << distributing[currp][i*spaceX+j];
}
fout<
□■□
□■□
□■□
->
...
2.
□■■
■□■
□■□
3.
□■■□
■□□■
□■■□
4.
■■
■■
5.
□■■□
■□□■
■□□■
□■■□
6.
□□■□
□■□■
■□□■
□■■□
7.
□■□
■□■
□■□
8.
■■□
■□■
□■■
9.
□□■■
□■□■
■□■□
□■□□
10.
□■□□
■□■□
□■□■
□□■□
11.
//左边界上
□□■■□□
□■■□□□
■□■□□■
■■□■■■
■□■□■□
□■■■□□
12.
//移动子(移动方向左下)
□■□
■□□
■■■
13.
//移动子(移动方向左上)
■■■
■□□
□■□
14.
//移动子(移动方向右下)
□□■
■□■
□■■
15.
□□□□□□□□□□□□□□□□
□□□□■□□□□□■□□□□□
□□□□■□□□□□■□□□□□
□□□□■■□□□■■□□□□□
□□□□□□□□□□□□□□□□
■■■□□■■□■■□□■■■□
□□■□■□■□■□■□■□□□
□□□□■■□□□■■□□□□□
□□□□□□□□□□□□□□□□
□□□□■■□□□■■□□□□□
□□■□■□■□■□■□■□□□
■■■□□■■□■■□□■■■□
□□□□□□□□□□□□□□□□
□□□□■■□□□■■□□□□□
□□□□■□□□□□■□□□□□
□□□□■□□□□□■□□□□□
□□□□□□□□□□□□□□□□
16.
□■□□□□
■□■□□□
□■□■□□
□□■□■□
□□□■□■
□□□□■□
17.
//循环变化
■■□□
■■□□
□□■■
□□■■
->
■■□□
■□□□
□□□■
□□■■
->
...
18.
//循环变化
□■■□
□□□■
■□□□
□■■□
->
□□■□
□■■□
□■■□
□■□□
->
...
19.
□■■□
■□□■
■□□■
□■■□
20.
//下边界
□■■□□□■■□
□■□□■□□■□
□□■■■■■□□
─────────
21.
//右上角
□■■□
□■□■
□□□■
□□■■
22.
//右下角
□□□□
□□■■
■□□■
■■■□
23.
...