📄 sharkfish.cpp
字号:
#include "SharkFish.h"
#include <malloc.h>
void SeaInit(Cell &matrix,int rows,int cols) //随机初始化海域生物
{
srand( (unsigned)time( NULL ) ); //设置随机种子
system("cls"); //清空屏幕
for(int i=0;i<rows;i++)
{
for(int j=0;j<cols;j++)
{
int RAND_SPAN=rand()%10; //获得随机数
if((RAND_SPAN>=0)&&(RAND_SPAN<5)) //如果随机数在范围一中
(&matrix+(i*cols+j))->SetType(FISH_TYPE); //设置细胞为小鱼类型
else if((RAND_SPAN>=5)&&(RAND_SPAN<7)) //如果随机数在范围二中
(&matrix+(i*cols+j))->SetType(SHARK_TYPE); //设置细胞为鲨鱼类型
else //其余情况
(&matrix+(i*cols+j))->SetType(EMPTY); //设置细胞为空白区域
}
}
}
int RandEatDiretion(Cell &matrix,int rows,int cols,int i,int j) //鲨鱼随机选择一条鱼吃
{
int EatAble[4]={0,0,0,0}; //存储可能的所有方向
int k=0; //可以吃的鱼的数量
srand( (unsigned)time( NULL ) ); //产生随机种子
if((&matrix+(i*cols+(j+1)%COLUMN))->GetType()==FISH_TYPE) //右侧有鱼吃
{
EatAble[k]=RIGHT; //存储方向
k++; //可选择的鱼数量加一
}
if((&matrix+((i+1)%ROW*cols+j))->GetType()==FISH_TYPE) //下侧有鱼吃
{
EatAble[k]=DOWN;
k++;
}
if((&matrix+(i*cols+(j-1+COLUMN)%COLUMN))->GetType()==FISH_TYPE) //左侧有鱼吃
{
EatAble[k]=LEFT;
k++;
}
if((&matrix+((i-1+ROW)%ROW*cols+j))->GetType()==FISH_TYPE) //上侧有鱼吃
{
EatAble[k]=UP;
k++;
}
if(k!=0) //有鱼可以选择吃
{
return EatAble[rand()%k]; //随机选择一条鱼吃
}
return NOTHING_TO_EAT; //没有鱼吃
}
int RandMoveDiretion(Cell &matrix,int rows,int cols,int i,int j) //随机选择一个方向移动
{
int MoveAble[4]={0,0,0,0}; //存储可以移动的方向
int k=0; //可以选择的方向数量
srand( (unsigned)time( NULL ) ); //产生随机种子
if((&matrix+(i*cols+(j+1)%COLUMN))->GetType()==EMPTY) //右侧可以移动
{
MoveAble[k]=RIGHT; //存储可移动的方向
k++; //可选择的数量加一
}
if((&matrix+((i+1)%ROW*cols+j))->GetType()==EMPTY) //下侧可以 移动
{
MoveAble[k]=DOWN;
k++;
}
if((&matrix+(i*cols+(j-1+COLUMN)%COLUMN))->GetType()==EMPTY) //左侧可以移动
{
MoveAble[k]=LEFT;
k++;
}
if((&matrix+((i-1+ROW)%ROW*cols+j))->GetType()==EMPTY) //上侧可以移动
{
MoveAble[k]=UP;
k++;
}
if(k!=0) //有方向可以选择移动
{
return MoveAble[rand()%k]; //在可选择的范围内随机移动
}
return NOWHERE_TO_MOVE; //没有空间可以移动
}
void EatFish(Cell &matrix,int rows,int cols,int i,int j,int EatDirection) //鲨鱼吃小鱼
{
if(EatDirection!=NOTHING_TO_EAT) //有鱼可以选择吃
{
(&matrix+(i*cols+j))->ClearStarve(); //将鲨鱼的饥饿时间清空
switch(EatDirection) //查看所选择的小鱼在哪个方向
{
case RIGHT: //右侧
*(&matrix+(i*cols+(j+1)%COLUMN))=*(&matrix+(i*cols+j)); //复制细胞数据到右侧的空间
(&matrix+(i*cols+j))->Clear(); //清空原来鲨鱼的空间
break;
case DOWN: //下侧
*(&matrix+((i+1)%ROW*cols+j))=*(&matrix+(i*cols+j));
(&matrix+(i*cols+j))->Clear();
break;
case LEFT: //左侧
*(&matrix+(i*cols+(j-1+COLUMN)%COLUMN))=*(&matrix+(i*cols+j));
(&matrix+(i*cols+j))->Clear();
break;
case UP: //上侧
*(&matrix+((i-1+ROW)%ROW*cols+j))=*(&matrix+(i*cols+j));
(&matrix+(i*cols+j))->Clear();
break;
}
}
else //鲨鱼没有鱼吃
{
(&matrix+(i*cols+j))->Starve(); //饥饿时间增加一
if((&matrix+(i*cols+j))->GetStarvationTime()==SHARK_STARVE_SPAN) //如果鲨鱼的饥饿时间到达生命极限
(&matrix+(i*cols+j))->Clear(); //鲨鱼由于没有食物而被饿死
}
}
void Move(Cell &matrix,int rows,int cols,int i,int j,int MoveDirection) //细胞进行移动
{
if(MoveDirection!=NOWHERE_TO_MOVE) //有方向可以移动
{
switch(MoveDirection) //查找所选的移动方向
{
case RIGHT: //向右移动
*(&matrix+(i*cols+(j+1)%COLUMN))=*(&matrix+(i*cols+j)); //把细胞数据复制到新位置
break;
case DOWN: //向下移动
*(&matrix+((i+1)%ROW*cols+j))=*(&matrix+(i*cols+j));
break;
case LEFT: //向左移动
*(&matrix+(i*cols+(j-1+COLUMN)%COLUMN))=*(&matrix+(i*cols+j));
break;
case UP: //向上移动
*(&matrix+((i-1+ROW)%ROW*cols+j))=*(&matrix+(i*cols+j));
break;
}
if((&matrix+(i*cols+j))->GetType()==SHARK_TYPE) //移动的是一条鲨鱼
{
if(((&matrix+(i*cols+j))->GetAge()!=0)&&(((&matrix+(i*cols+j))->GetAge()%SHARK_BORN_AGE)==0))
{ //鲨鱼到了生育年龄
(&matrix+(i*cols+j))->Clear(); //清空原来空间
(&matrix+(i*cols+j))->SetType(SHARK_TYPE); //设置新的鲨鱼属性
}
else
{ //如果没有到达生育年龄
(&matrix+(i*cols+j))->Clear(); //清空原来的空间
}
}
else if((&matrix+(i*cols+j))->GetType()==FISH_TYPE) //移动的是一条小鱼
{
if(((&matrix+(i*cols+j))->GetAge()!=0)&&(((&matrix+(i*cols+j))->GetAge()%FISH_BORN_AGE)==0))
{ //小鱼到达生育年龄
(&matrix+(i*cols+j))->Clear(); //清空原来的空间
(&matrix+(i*cols+j))->SetType(FISH_TYPE); //设置新的小鱼属性
}
else
{ //如果没有到达生育年龄
(&matrix+(i*cols+j))->Clear(); //清空原来的空间
}
}
}
}
void OutPutSea(Cell &matrix,int rows,int cols) //输出海域的状态
{
/* //输出细胞状态
for(int i=0;i<rows;i++)
{
for(int j=0;j<cols;j++)
{
(&matrix+(i*cols+j))->PrintCell();
}
cout<<endl;
}
*/
for(int i=0;i<rows;i++) //图形输出鲨鱼和小鱼的状态
{
for(int j=0;j<cols;j++)
{
if((&matrix+(i*cols+j))->GetType()==SHARK_TYPE) //用 ■ 表示鲨鱼
cout<<"■";
else if((&matrix+(i*cols+j))->GetType()==FISH_TYPE) //用 ⊙ 表示小鱼
cout<<"⊙";
else
cout<<" "; //用空格表示空白区域
}
cout<<endl;
}
}
int GetCellListLen(struct CellNode *ListHead) //获得细胞链表的长度
{
struct CellNode *p=ListHead; //获得链表头
int lenth=0; //初始化长度
while(p!=NULL) //指针非空进行循环
{
lenth++; //长度加一
p=p->next; //链表指针向后移动
}
return lenth; //返回链表长度
}
struct CellNode *InsertCellList(struct CellNode *ListHead,Cell* CellElem,int x,int y) //将细胞随机插入链表
{
struct CellNode *p=ListHead; //获得链表头
struct CellNode *s=NULL; //定义TEMP节点指针
int j=0; //定义位置循环变量
srand( (unsigned)time( NULL ) ); //设置随机种子
int index=rand()%GetCellListLen(ListHead); //产生随机插入位置
while(p&&j<index-1){p=p->next;++j;} //查找随机插入位置
s=(struct CellNode *)malloc(sizeof(CellNode)); //为TEMP节点分配空间
s->NodeElem=CellElem; //为TEMP节点附值
s->x=x;
s->y=y;
s->next=p->next; //将TEMP节点插入指定位置
p->next=s;
return ListHead; //返回细胞链表头
}
struct CellNode *CreatCellList(struct CellNode *ListHead,Cell &matrix,int rows,int cols,int TYPE)
{ //创建细胞链表
ListHead=(struct CellNode *)malloc(sizeof(CellNode)); //产生表头节点空间
ListHead->next=NULL;
for(int i=0;i<rows;i++) //在海域内进行查找
{
for(int j=0;j<cols;j++)
{
if((&matrix+(i*cols+j))->GetType()==TYPE) //在海域内查找指定细胞类型
{
ListHead=InsertCellList(ListHead,(&matrix+(i*cols+j)),i,j); //将指定的类型细胞插入相应链表
}
}
}
return ListHead; //返回链表头
}
void PrintList(struct CellNode *ListHead) //输出细胞链表的元素信息
{
struct CellNode *p=ListHead->next; //定义节点指针
while(p!=NULL) //顺链表循环
{ //输出节点信息
cout<<"{"<<p->NodeElem->GetType()<<","<<p->NodeElem->GetAge()<<","<<p->x<<","<<p->y<<"}"<<endl;
p=p->next; //向链表后步进
}
}
struct CellNode *GetCell(struct CellNode *ListHead) //获得链表头节点并在表中删除此节点
{
struct CellNode *p=ListHead->next; //定义节点指针
if(p==NULL) //如果指针空,则返回空指针
{
return NULL;
}
else //若不空
{
ListHead->next=p->next; //在节点中删除此节点
return p; //返回细胞节点
}
}
void Action(struct CellNode* List,Cell &matrix,int rows,int cols,int TYPE) //海洋生物的行动
{
if(TYPE==SHARK_TYPE) //如果是鲨鱼类型
{
struct CellNode* SharkNode=GetCell(List); //获得第一个鲨鱼节点
while(SharkNode) //当节点非空则进行循环
{
int i=SharkNode->x; //获得鲨鱼节点位置信息
int j=SharkNode->y;
SharkNode->NodeElem->Grow(); //鲨鱼年龄增长一个时间单位
if(SharkNode->NodeElem->GetAge()==SHARK_LIFE_SPAN) //如果鲨鱼到达生命极限
SharkNode->NodeElem->Clear(); //鲨鱼死亡
int EatDirection=RandEatDiretion(matrix,rows,cols,i,j); //获得可以吃的鱼
EatFish(matrix,rows,cols,i,j,EatDirection); //吃所选择的鱼
if(EatDirection==NOTHING_TO_EAT) //如果没有鱼可以吃
{
int MoveDirection=RandMoveDiretion(matrix,rows,cols,i,j); //选择可以移动的方向
if(NOWHERE_TO_MOVE!=MoveDirection) //如果有空间进行移动
Move(matrix,rows,cols,i,j,MoveDirection); //鲨鱼按照所选方向移动
else //没有空间移动
SharkNode->NodeElem->Clear(); //鲨鱼由于密度太大而死
}
SharkNode=GetCell(List); //获得下一个细胞节点
}
}
else if(TYPE==FISH_TYPE) //如果是小鱼类型
{
struct CellNode* FishNode=GetCell(List); //获得第一个小鱼节点信息
while(FishNode) //当节点非空则进行循环
{
if(FishNode->NodeElem->GetType()==FISH_TYPE) //《注意》原来存储的小鱼节点可能已经
{ //被鲨鱼吃掉而换成了鲨鱼类型,这里处理没有改变的节点
int i=FishNode->x; //获得节点位置信息
int j=FishNode->y;
FishNode->NodeElem->Grow(); //小鱼年龄增加一个时间单位
if(FishNode->NodeElem->GetAge()==FISH_LIFE_SPAN) //如果小鱼到达生命极限
FishNode->NodeElem->Clear(); //小鱼死亡
int MoveDirection=RandMoveDiretion(matrix,rows,cols,i,j); //随机选择移动的方向
if(NOWHERE_TO_MOVE!=MoveDirection) //如果有空间可以移动
Move(matrix,rows,cols,i,j,MoveDirection); //移动到新的位置
else //没有空间移动
FishNode->NodeElem->Clear(); //小鱼由于密度太大而死亡
}
FishNode=GetCell(List); //获得下一个细胞节点
}
}
}
void main()
{
Cell Sea[ROW][COLUMN]; //定义海域矩阵
time_t start, finish; //定义起止时间
double elapsed_time; //定义时间差
time( &start ); //获得开始时间
srand( (unsigned)time( NULL ) ); //设置随机种子
SeaInit(Sea[0][0],ROW,COLUMN); //初始化海域生物信息
for(int Time=0;Time<TIMELOOP;Time++) //在迭代次数内循环
{
system("cls"); //清除屏幕
struct CellNode* SharkList=NULL; //定义鲨鱼链表
struct CellNode* FishList=NULL; //定义小鱼链表
SharkList=CreatCellList(SharkList,Sea[0][0],ROW,COLUMN,SHARK_TYPE); //创建鲨鱼链表
FishList=CreatCellList(FishList,Sea[0][0],ROW,COLUMN,FISH_TYPE); //创建小鱼链表
Action(SharkList,Sea[0][0],ROW,COLUMN,SHARK_TYPE); //鲨鱼的动作
Action(FishList,Sea[0][0],ROW,COLUMN,FISH_TYPE); //小鱼的动作
OutPutSea(Sea[0][0],ROW,COLUMN); //输出迭代一次后的海域情况
// getchar();
}
time( &finish ); //获得结束时间
elapsed_time = difftime( finish, start ); //计算程序运行时间
cout<<"程序运行时间:"<<elapsed_time<<"秒"<<endl;
cout<<"自动机程序运行完毕,请按任意键退出";
getchar();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -