题目: 模拟一个微型生态系统。有青草、兔子、狐狸三种生物。可以用网格表示整个环境,每个格子内用不同字母表示不同事物:空地E青草G兔子R狐狸F。系统规则如下:
1)初始状态随机出现GRF;
2)若格子为G,下一轮其周边八个格子中为E的格子中会至少有一个变为G;
3)若格子为R,若其周围八个格子都没有G或其中一个出现F,则下一轮此格子为E;否则其中一个为G的格子变为R;
4)若格子为F,其周围八个格子都没有R,则下一轮此格子为E;否则其中一个为R的格子变成F;
5)若格子为E,则下一轮会以一定的概率变为G。
请分析并画出类结构图,利用面向对象程序设计思想,完成模拟过程。(必须用到类的继承、虚函数)
问题分析:
感觉没有很大的必要对每一种生物创建一个类,并进行派生,所以这里我只创建了两个类,一个世界(world)作为基类,一个生态系统(ShengTai)作为派生类,继承于基类(world),输出函数(Display)作为虚函数,创建基类指针调用派生类的虚函数。类结构图如下:
代码实现:(运行环境为Microsoft Visual Studio 2010)
/*初始化生态系统大小为10*10(可以改变),空地变为青草地的概率为60%(可以改变),规则中某些地方指出某些情况下,至少一个改变或者其中一个地方改变,这里均按照从上到下从左到右的顺序,以出现满足条件的第一个进行改变,其余不变。*/
#include<iostream>
#include<ctime>
#include<cstdlib>
using namespace std;
const int col = 10;
const int row = 10;//初始化生态系统大小<col*row>
const int TurnGrass = 60;//空地变为青草地的概率
class world
{
public:
void Init();
virtual void Display();
};
void world::Init()
{
cout<<"world init"<<endl;
}
void world::Display()
{
cout<<"nothing found,world empty!"<<endl;
}
class ShengTai:public world
{
public:
void Init();//初始化
void Develop();//演化
void Display();//输出状态
void Traverse();//遍历
private:
int s[col][row];//存放0,1,2,3,分别代表空地青草兔子狐狸
char life;//存放生物或者空地
};
void ShengTai::Init()
{
int i,j;
srand((unsigned)time(NULL));
for(i=0;i<col;i++)
for(j=0;j<row;j++)
s[i][j] = rand()%(3-0+1)+0;
Traverse();
}
void ShengTai::Traverse()
{
int i,j;
for(i=0;i<col;i++)
for(j=0;j<row;j++)
switch(s[i][j])
{
case 0:life = 'E';break;
case 1:life = 'G';break;
case 2:life = 'R';break;
case 3:life = 'F';break;
default:cout<<"error traverse"<<endl;
}
}
void ShengTai::Display()
{
int i,j;
for(i=0;i<col;i++)
{
for(j=0;j<row;j++)
switch(s[i][j])
{
case 0:cout<<"E"<<" ";break;
case 1:cout<<"G"<<" ";break;
case 2:cout<<"R"<<" ";break;
case 3:cout<<"F"<<" ";break;
default:cout<<"error display"<<endl;
}
cout<<endl;
}
cout<<endl;
}
void ShengTai::Develop()
{
int i,j,turned = 0;
int tmp[col][row];
for(i=0;i<col;i++)
for(j=0;j<row;j++)
tmp[i][j] = 5;
for(i=0;i<col;i++)
for(j=0;j<row;j++)
switch(s[i][j])
{
case 0:
{
int k;
k = rand()%(100-1+1)+1;
if(k >= TurnGrass)
tmp[i][j] = 1;
break;
}
case 1:
{
turned = 0;
if(s[i-1][j-1] == 0)
{
tmp[i-1][j-1] = 1;
turned = 1;
}
if(s[i-1][j] == 0&&turned == 0)
{
tmp[i-1][j] = 1;
turned = 1;
}
if(s[i-1][j+1] == 0&&turned == 0)
{
tmp[i-1][j+1] = 1;
turned = 1;
}
if(s[i][j-1] == 0&&turned == 0)
{
tmp[i][j-1] = 1;
turned = 1;
}
if(s[i][j+1] == 0&&turned == 0)
{
tmp[i][j+1] = 1;
turned = 1;
}
if(s[i+1][j-1] == 0&&turned == 0)
{
tmp[i+1][j-1] = 1;
turned = 1;
}
if(s[i+1][j] == 0&&turned == 0)
{
tmp[i+1][j] = 1;
turned = 1;
}
if(s[i+1][j+1] == 0&&turned == 0)
{
tmp[i+1][j+1] = 1;
turned = 1;
}
break;
}
case 2:
{
turned = 0;
if(s[i-1][j-1] == 3)
{
tmp[i-1][j-1] = 3;
turned = 1;
}
if(s[i-1][j] == 3&&turned == 0)
{
tmp[i-1][j] = 3;
turned = 1;
}
if(s[i-1][j+1] == 3&&turned == 0)
{
tmp[i-1][j+1] = 3;
turned = 1;
}
if(s[i][j-1] == 3&&turned == 0)
{
tmp[i][j-1] = 3;
turned = 1;
}
if(s[i][j+1] == 3&&turned == 0)
{
tmp[i][j+1] = 3;
turned = 1;
}
if(s[i+1][j-1] == 3&&turned == 0)
{
tmp[i+1][j-1] = 3;
turned = 1;
}
if(s[i+1][j] == 3&&turned == 0)
{
tmp[i+1][j] = 3;
turned = 1;
}
if(s[i+1][j+1] == 3&&turned == 0)
{
tmp[i+1][j+1] = 3;
turned = 1;
}
if(turned == 0&&
s[i-1][j-1] != 1&&s[i-1][j] != 1&&
s[i-1][j+1] != 1&&s[i][j-1] != 1&&
s[i][j+1] != 1&&s[i+1][j-1] != 1&&
s[i+1][j] != 1&&s[i+1][j+1] != 1)
{
if(s[i-1][j-1] == 1)
{
tmp[i-1][j-1] = 2;
turned = 1;
}
if(s[i-1][j] == 1&&turned == 0)
{
tmp[i-1][j] = 2;
turned = 1;
}
if(s[i-1][j+1] == 1&&turned == 0)
{
tmp[i-1][j+1] = 2;
turned = 1;
}
if(s[i][j-1] == 1&&turned == 0)
{
tmp[i][j-1] = 2;
turned = 1;
}
if(s[i][j+1] == 1&&turned == 0)
{
tmp[i][j+1] = 2;
turned = 1;
}
if(s[i+1][j-1] == 1&&turned == 0)
{
tmp[i+1][j-1] = 2;
turned = 1;
}
if(s[i+1][j] == 1&&turned == 0)
{
tmp[i+1][j] = 2;
turned = 1;
}
if(s[i+1][j+1] == 1&&turned == 0)
{
tmp[i+1][j+1] = 2;
turned = 1;
}
}
break;
}
case 3:
{
turned = 0;
if(i == 0)
{
if(j == 0)
{
if(s[i][j+1] != 2&&s[i+1][j] != 2&&s[i+1][j+1] != 2&&turned == 0)
{
tmp[i][j] = 0;
turned = 1;
}
}
else if(j == row-1)
{
if(s[i][j-1] != 2&&s[i+1][j-1] != 2&&s[i+1][j] != 2&&turned == 0)
{
tmp[i][j] = 0;
turned = 1;
}
}
else
{
if(s[i][j-1] != 2&&s[i][j+1] != 2&&s[i+1][j-1] != 2&&s[i+1][j] != 2&&s[i+1][j+1] != 2&&turned == 0)
{
tmp[i][j] = 0;
turned = 1;
}
}
}
else if(i == col-1)
{
if(j == 0)
{
if(s[i-1][j] != 2&&s[i-1][j-1] != 2&&s[i][j+1] != 2&&turned == 0)
{
tmp[i][j] = 0;
turned = 1;
}
}
else if(j == row-1)
{
if(s[i-1][j-1] != 2&&s[i-1][j] != 2&&s[i][j-1] != 2&&turned == 0)
{
tmp[i][j] = 0;
turned = 1;
}
}
else
{
if(s[i-1][j-1] != 2&&s[i-1][j] != 2&&s[i-1][j+1] != 2&&s[i][j-1] != 2&&s[i][j+1] != 2&&turned == 0)
{
tmp[i][j] = 0;
turned = 1;
}
}
}
else
{
if(s[i-1][j-1] != 2&&s[i-1][j] != 2&&s[i-1][j+1] != 2&&s[i][j-1] != 2&&s[i][j+1] != 2&&s[i+1][j-1] != 2&&s[i+1][j] != 2&&s[i+1][j+1] != 2)
{
tmp[i][j] = 0;
turned = 1;
}
}
if(s[i-1][j-1] == 2&&turned == 0)
{
tmp[i-1][j-1] = 3;
turned = 1;
}
if(s[i-1][j] == 2&&turned == 0)
{
tmp[i-1][j] = 3;
turned = 1;
}
if(s[i-1][j+1] == 2&&turned == 0)
{
tmp[i-1][j+1] = 3;
turned = 1;
}
if(s[i][j-1] == 2&&turned == 0)
{
tmp[i][j-1] = 3;
turned = 1;
}
if(s[i][j+1] == 2&&turned == 0)
{
tmp[i][j+1] = 3;
turned = 1;
}
if(s[i+1][j-1] == 2&&turned == 0)
{
tmp[i+1][j-1] = 3;
turned = 1;
}
if(s[i+1][j] == 2&&turned == 0)
{
tmp[i+1][j] = 3;
turned = 1;
}
if(s[i+1][j+1] == 2&&turned == 0)
{
tmp[i+1][j+1] = 3;
turned = 1;
}
break;
}
default:cout<<"error develop"<<endl;
}
for(i=0;i<col;i++)
for(j=0;j<row;j++)
if(tmp[i][j] != 5)
{
s[i][j] = tmp[i][j];
}
Traverse();
Display();
}
int main()
{
world me;
me.Init();
ShengTai your;
your.Init();
world *p = &me;
p->Display();
p = &your;
p->Display();//通过基类指针调用派生类的虚函数
ShengTai w;
w.Init();
int i;
cout<<"input 1 to display,2 to develop,3 to exit."<<endl;
cin>>i;
while(i != 3)
{
if(i == 1)
w.Display();
if(i == 2)
w.Develop();
cout<<"input 1 to display,2 to develop,3 to exit."<<endl;
cin>>i;
}
return 0;
}
运行结果:
1. 类的继承与虚函数的实现
2. 生态系统中空地、青草、兔子、狐狸演化的过程
演化一次
演化二次