📄 func.cpp
字号:
NewCell=(&matrix+(i*cols+(j-1+COLUMN)%COLUMN));
break;
case UP: //上侧
NewCell=(&matrix+((i-1)*cols+j));
break;
}
*NewCell=*OrientCell; //改变选定的细胞
OrientCell->Type=0; //清空原来鲨鱼的空间
OrientCell->Age=0;
OrientCell->StarvationTime=0;
}
else //鲨鱼没有鱼吃
{
(&matrix+(i*cols+j))->StarvationTime++; //饥饿时间增加一
if((&matrix+(i*cols+j))->StarvationTime==SHARK_STARVE_SPAN) //如果鲨鱼的饥饿时间到达生命极限
{
(&matrix+(i*cols+j))->Type=0;; //清空原来鲨鱼的空间
(&matrix+(i*cols+j))->Age=0;
(&matrix+(i*cols+j))->StarvationTime=0; //鲨鱼由于没有食物而被饿死
}
}
return SUCCEED;
}
void Move(Cell &matrix,int rows,int cols,int i,int j,int MoveDirection,MPI_Datatype MsgType,MPI_Datatype CellType) //细胞进行移动
{
if(MoveDirection!=NOWHERE_TO_MOVE) //有方向可以移动
{
Cell* OrientCell=(&matrix+(i*cols+j));//定义旧细胞位置的地址,并赋予现在细胞的地址
Cell* NewCell; //定义新细胞位置的地址,用于后面的操作
switch(MoveDirection) //查找所选的移动方向
{
case RIGHT: //向右移动
NewCell=(&matrix+(i*cols+(j+1)%COLUMN)); //获取需要修改的细胞空间的地址
break;
case DOWN: //向下移动
NewCell=(&matrix+((i+1)*cols+j));
break;
case LEFT: //向左移动
NewCell=(&matrix+(i*cols+(j-1+COLUMN)%COLUMN));
break;
case UP: //向上移动
NewCell=(&matrix+((i-1)*cols+j));
break;
}
*NewCell=*OrientCell; //改变选定的细胞
//在不同情况下处理原来的细胞,例如生育问题
if(OrientCell->Type==SHARK_TYPE) //移动的是一条鲨鱼,在移动中处理生育问题
{
if((OrientCell->Age!=0)&&((OrientCell->Age%SHARK_BORN_AGE)==0))
{ //鲨鱼到了生育年龄
OrientCell->Type=0;; //清空原来鲨鱼的空间
OrientCell->Age=0;
OrientCell->StarvationTime=0;
OrientCell->Type=SHARK_TYPE; //设置新的鲨鱼属性
}
else
{ //如果没有到达生育年龄
OrientCell->Type=0;; //清空原来鲨鱼的空间
OrientCell->Age=0;
OrientCell->StarvationTime=0;
}
}
else if(OrientCell->Type==FISH_TYPE) //移动的是一条小鱼,在移动中处理生育问题
{
if((OrientCell->Age!=0)&&((OrientCell->Age%FISH_BORN_AGE)==0))
{ //小鱼到达生育年龄
OrientCell->Type=0;; //清空原来鱼的空间
OrientCell->Age=0;
OrientCell->StarvationTime=0;
OrientCell->Type=FISH_TYPE; //设置新的小鱼属性
}
else
{ //如果没有到达生育年龄
OrientCell->Type=0;; //清空原来鱼的空间
OrientCell->Age=0;
OrientCell->StarvationTime=0;
}
}
}
}
void Action(struct CellNode* List,Cell &matrix,int rows,int cols,int TYPE,MPI_Datatype MsgType,MPI_Datatype CellType) //海洋生物的行动
{
Cell* CurrentCell;
if(TYPE==SHARK_TYPE) //如果是鲨鱼类型
{
struct CellNode* SharkNode=GetCell(List); //获得第一个鲨鱼节点
while(SharkNode) //当节点非空则进行循环
{
int i=SharkNode->x; //获得鲨鱼节点位置信息
int j=SharkNode->y;
SharkNode->NodeElem->Age++; //鲨鱼年龄增长一个时间单位
CurrentCell=(&matrix+(i*cols+j));//获取现在正在操作的细胞地址
if(SharkNode->NodeElem->Age==SHARK_LIFE_SPAN) //如果鲨鱼到达生命极限
{
CurrentCell->Type=0;; //清空原来鲨鱼的空间
CurrentCell->Age=0;
CurrentCell->StarvationTime=0; //鲨鱼死亡
}
int EatDirection=RandEatDiretion(matrix,rows,cols,i,j); //获得可以吃的鱼
EatFish(matrix,rows,cols,i,j,EatDirection,MsgType,CellType); //吃所选择的鱼
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,MsgType,CellType); //鲨鱼按照所选方向移动
else //没有空间移动
{
CurrentCell->Type=0;; //清空原来鲨鱼的空间
CurrentCell->Age=0;
CurrentCell->StarvationTime=0; //鲨鱼由于密度太大而死
}
}
SharkNode=GetCell(List); //获得下一个细胞节点
}
}
else if(TYPE==FISH_TYPE) //如果是小鱼类型
{
struct CellNode* FishNode=GetCell(List); //获得第一个小鱼节点信息
while(FishNode) //当节点非空则进行循环
{
if(FishNode->NodeElem->Type==FISH_TYPE) //《注意》原来存储的小鱼节点可能已经
{ //被鲨鱼吃掉而换成了鲨鱼类型,这里处理没有改变的节点
int i=FishNode->x; //获得节点位置信息
int j=FishNode->y;
FishNode->NodeElem->Age++; //小鱼年龄增加一个时间单位
CurrentCell=(&matrix+(i*cols+j));//获取现在正在操作的细胞地址
if(FishNode->NodeElem->Age==FISH_LIFE_SPAN) //如果小鱼到达生命极限
{
CurrentCell->Type=0;; //清空原来的空间
CurrentCell->Age=0;
CurrentCell->StarvationTime=0; //小鱼死亡
}
int MoveDirection=RandMoveDiretion(matrix,rows,cols,i,j); //随机选择移动的方向
if(NOWHERE_TO_MOVE!=MoveDirection) //如果有空间可以移动
Move(matrix,rows,cols,i,j,MoveDirection,MsgType,CellType); //移动到新的位置
else //没有空间移动
{
CurrentCell->Type=0;; //清空原来鱼的空间
CurrentCell->Age=0;
CurrentCell->StarvationTime=0; //小鱼由于密度太大而死亡
}
}
FishNode=GetCell(List); //获得下一个细胞节点
}
}
}
int InBoundary(int row,int x) //判定细胞是否在边界区域,并确定返回所在区域编号
{
if((x>1)&&(x<row-2)) //在获得的区域内从第三行到倒数第三行属于内部区域
{
return IN_WORKFIELD; //返回工作区域编号
}
else if((x<=1)&&(x>=0)) //在获得区域的前两行属于上边界
{
return IN_UP_BOUNDARY; //返回上边界的编号
}
else if((x>=row-2)&&(x<=row-1)) //在获得区域的最后两行属于下边界
{
return IN_BOTTOM_BOUNDARY; //返回下边界的编号
}
return -1; //错误!输入的坐标不在所获区域内!
}
void DealApplication(Cell & GotData,int x,int y,int rank,MPI_Datatype MsgType,MPI_Datatype CellType)
{
MPI_Status status;//定义进程状态
Msg msg; //定义消息变量
int pos[2]; //定义索要数据的坐标
pos[0]=x; //给坐标附值
pos[1]=y;
msg.Type=MSG_APPLICATION; //子进程完成工作向主进程发送申请消息
msg.Source=rank; //设置消息源
MPI_Send(&msg,1,MsgType,0,rank,MPI_COMM_WORLD);//发送申请
MPI_Recv(&msg,1,MsgType,0,0,MPI_COMM_WORLD,&status); //接收同意或拒绝的消息回复
if(MSG_AGREE==msg.Type)//如果主进程同意发送
{
MPI_Send(&pos,2,MPI_INT,0,rank,MPI_COMM_WORLD); //向主进程发送数据坐标
MPI_Recv(&GotData,1,CellType,0,0,MPI_COMM_WORLD,&status);//接受主进程发来的数据信息
cout<<"("<<GotData.Type<<","<<GotData.Age<<","<<GotData.StarvationTime<<")"<<"("<<pos[0]<<","<<pos[1]<<")"<<endl;
}
}
void PosMap(int &x,int &y,int i,int j)//把子进程数据的坐标映射成主进程数据的坐标
{
int rank,size,workAmount;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);//获得进程号
MPI_Comm_size(MPI_COMM_WORLD, &size);//获得进程总数
workAmount=(int)((double)ROW/(size-1)+.5); //平均分配子进程工作量(均分上取整)
x=(rank-1)*workAmount+i; //映射坐标
y=j;
}
bool SelfCheck(Cell &matrix,int rows,int cols,int i,int j,Cell &Self)
{
if((&matrix+(i*cols+j))->Type==Self.Type)
if((&matrix+(i*cols+j))->Age==Self.Age)
if((&matrix+(i*cols+j))->StarvationTime==Self.StarvationTime)
return true;
return false;
}
void UpDateSubData(Cell &matrix,int rows,int cols,int i,int j,Cell &Self)
{
(&matrix+(i*cols+j))->Type=Self.Type;
(&matrix+(i*cols+j))->Age=Self.Age;
(&matrix+(i*cols+j))->StarvationTime=Self.StarvationTime;
}
void UpDateMainData()
{
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -