搜索算法一直是ai中的核心讨论内容.基本都是从效率考虑,当然数量级很小的话或者格局普通,没什么差别?但一到涉及到特殊的情况,恐怕就分出优劣了;当然,不同的算法,可能适合不同的场合.
此处讨论一下双向搜索算法,但不涉及到算法思想的揉和,此处就不讲a*的思想考虑进去…
双向搜索算法:较之普通搜索,搜索面积是1/2;
在一方出现闭环现象时,可以很快结束搜索,但其他算法,估计要把源闭环中所有节点搜尽;
此处以c语言来实现双向搜索算法…有兴趣的朋友,可以考虑将a*算法思想加入,也许效率更好…不过如你加入的话,敬请让我学习一下…
typedef struct _POINT
{
int nx;
int ny;
}POINT;
typedef struct _WORLDUNIT
{
BYTE nColorIndex;//颜色索引
boolean bClear; //
boolean bFind; //是否已经查找过了…
POINT Father; ///正向,逆向求解路径
int nChild;//表示数目了.
POINT CHILD[4];///正向,逆向求解路径
}WorldUnit;
void ResetPathData(AIGoogleApp * pMe)//重置搜索路径的所有数据….
{
int x,y;
for(x=0;x
{
for(y=0;y
{
pMe->Cell[x][y].nChild=0;
pMe->Cell[x][y].Father.nx=NOVALUE;
pMe->Cell[x][y].Father.ny=NOVALUE;
pMe->Cell[x][y].bFind =FALSE;
pMe->Cell[x][y].bClear=FALSE;
}
}
//已保存数据也要重置了.
}
void InitFindData(AIGoogleApp * pMe)//初始化搜索的数据了….
{
pMe->nSelOld=1; ///正在目标搜索的节点数目
pMe->SelOld[0].nx =pMe->nSelx; ///正在目标搜索的节点
pMe->SelOld[0].ny =pMe->nSely;
pMe->Cell[pMe->nSelx][pMe->nSely].bFind=TRUE; 标志为查找过了…
pMe->nSelNew=0; //新添加的可搜索节点个数
pMe->nAimOld=1; ///正在目标搜索的节点数目,主要是双向的问题,才这样定义.
pMe->AimOld[0].nx =pMe->nAimx;
pMe->AimOld[0].ny =pMe->nAimy;
pMe->Cell[pMe->nAimx][pMe->nAimy].bFind=TRUE;
pMe->nAimNew=0;
}
static boolean FindGoodPath(AIGoogleApp * pMe)
{
int x,y;//用于自身周围的数据了.
int m,n;//临时变量
ResetPathData(pMe);//重置数据,然后开始了.
InitFindData(pMe); //重置查找数据了.
//从两个点出发查找问题.吧
while((pMe->nSelOld!=0)&&(pMe->nAimOld!=0))//任意一个正在搜索的节点集为空的话,停止搜索…
{
//处理了,先处理选中的,再处理目的的.
//逐个判断算了
/*
if(pMe->nSelOld==0)
{
}
if(pMe->nAimOld==0)
{
}
*/
while(pMe->nSelOld!=0)//将该外圈全部查找完毕才算结束了.
{
//首先不可能是了.原因:是的话就不可能调用查找路径了.
//把已经浏览过得给毖掉.哈哈,就可以了.
x=pMe->SelOld[pMe->nSelOld-1].nx;
y=pMe->SelOld[pMe->nSelOld-1].ny;
////////////////////////////////////
pMe->Cell[x][y].bFind=TRUE;
////////////////////////////////////
//上面的判断
m=x-1;
n=y;
if(m>=0)
{
if(FindOrAdd(pMe,m,n,x,y,0,TRUE))//检测是否查找到了,呵呵…
{
return TRUE;
}
}
//下面的判断
m=x+1;
n=y;
if(m
{
if(FindOrAdd(pMe,m,n,x,y,1,TRUE)) //检测是否查找到了,呵呵
{
return TRUE;
}
}
//左面的判断
m=x;
n=y-1;
if(n>=0)
{
if(FindOrAdd(pMe,m,n,x,y,2,TRUE)) //检测是否查找到了,呵呵
{
return TRUE;
}
}
//右面的判断
m=x;
n=y+1;
if(n
{
if(FindOrAdd(pMe,m,n,x,y,3,TRUE)) //检测是否查找到了,呵呵
{
return TRUE;
}
}
pMe->nSelOld--;
}
//然后新的赋给老的
//新的赋给老的
NewToOld(pMe,FALSE);//将新生成的搜索集赋给老的了…
////////
while(pMe->nAimOld!=0)//将该外圈全部查找完毕才算结束了.
{
//首先不可能是了.原因:是的话就不可能调用查找路径了.
//把已经浏览过得给毖掉.哈哈,就可以了.
x=pMe->AimOld[pMe->nAimOld-1].nx;
y=pMe->AimOld[pMe->nAimOld-1].ny;
////////////////////////////////////
pMe->Cell[x][y].bFind=TRUE;
////////////////////////////////////
//上面的判断
m=x-1;
n=y;
if(m>=0)
{
if(FindOrAdd(pMe,m,n,x,y,0,FALSE))
{
return TRUE;
}
}
//下面的判断
m=x+1;
n=y;
if(m
{
if(FindOrAdd(pMe,m,n,x,y,1,FALSE))
{
return TRUE;
}
}
//左面的判断
m=x;
n=y-1;
if(n>=0)
{
if(FindOrAdd(pMe,m,n,x,y,2,FALSE))
{
return TRUE;
}
}
//右面的判断
m=x;
n=y+1;
if(n
{
if(FindOrAdd(pMe,m,n,x,y,3,FALSE))
{
return TRUE;
}
}
pMe->nAimOld--;
}
//然后新的赋给老的
NewToOld(pMe,TRUE);
}
return FALSE;
}
boolean FindOrAdd(AIGoogleApp * pMe,int m,int n,int x,int y,int nChild,boolean bInAim)
{
POINT ToCheck;
if(pMe->Cell[m][n].nColorIndex!=0)
{
return FALSE;
}
ToCheck.nx=m;
ToCheck.ny=n;
if(CheckFind(pMe,ToCheck,bInAim))
{
pMe->PosFind.nx=ToCheck.nx ;
pMe->PosFind.ny=ToCheck.ny ;
ConStructPath(pMe,x,y,bInAim);//转过去的是找到点的准父 接点了.但目前尚无父子关系.
return TRUE;
}
else
{
if(pMe->Cell[m][n].bFind==TRUE)
return FALSE;
if(bInAim)
{
pMe->Cell[x][y].CHILD[nChild].nx=m;//将其儿子进行赋值
pMe->Cell[x][y].CHILD[nChild].ny=n;
pMe->SelNew[pMe->nSelNew].nx=m;
pMe->SelNew[pMe->nSelNew].ny=n;
pMe->nSelNew++;//儿子数目增加
pMe->Cell[m][n].Father.nx=x;//儿子指向父亲
pMe->Cell[m][n].Father.ny=y;
pMe->Cell[m][n].bFind=TRUE;//设置为已经找到过了.
}
else
{
pMe->Cell[x][y].CHILD[nChild].nx=m;//将其儿子进行赋值
pMe->Cell[x][y].CHILD[nChild].ny=n;
pMe->AimNew[pMe->nAimNew].nx=m;
pMe->AimNew[pMe->nAimNew].ny=n;
pMe->nAimNew++;//儿子数目增加
pMe->Cell[m][n].Father.nx=x;//儿子指向父亲
pMe->Cell[m][n].Father.ny=y;
pMe->Cell[m][n].bFind=TRUE;//设置为已经找到过了.
}
}
//检测是否找到了.如果找到退出.
//如果没找到呢,就添加到新的里面去
//进行处理
return FALSE;
}
boolean CheckFind(AIGoogleApp * pMe,POINT ToCheck,boolean bInAim)
{
int x;
if(bInAim)//如果在目标里查找
{
for(x=0;x
{
if(IsEqual(pMe,ToCheck,pMe->AimOld[x]))
{
return TRUE;
}
}
}
else
{
for(x=0;x
{
if(IsEqual(pMe,ToCheck,pMe->SelOld[x]))
{
return TRUE;
}
}
}
return FALSE;
}
///////////////////////////////////////////////////
boolean IsEqual(AIGoogleApp * pMe,POINT Check1,POINT Check2)
{
if((Check1.nx==Check2.nx)&&(Check1.ny==Check2.ny))
return TRUE;
else
return FALSE;
}
//////////////////////////////////////////////////
////////////////////////////
void NewToOld(AIGoogleApp * pMe,boolean bAim)
{
int x;
if(bAim)
{
pMe->nAimOld=0;
for(x=0;x
{
pMe->AimOld[pMe->nAimOld].nx =pMe->AimNew[x].nx;
pMe->AimOld[pMe->nAimOld].ny =pMe->AimNew[x].ny;
pMe->nAimOld++;
}
pMe->nAimNew=0;
}
else
{
pMe->nSelOld=0;
for(x=0;x
{
pMe->SelOld[pMe->nSelOld].nx =pMe->SelNew[x].nx;
pMe->SelOld[pMe->nSelOld].ny =pMe->SelNew[x].ny;
pMe->nSelOld++;
}
pMe->nSelNew=0;
}
}
///////////////////////////////////////////////////////
void ConStructPath(AIGoogleApp * pMe,int x,int y,boolean bAim)
{
int x1,y1,m,n;
int nChildx,nChildy;
//转过去的是找到点的准父 接点了.但目前尚无父子关系.
PathToSel(pMe,x,y,bAim);
PathToAim(pMe,x,y,bAim);
if(bAim)//连接起来了//
{
pMe->Cell[x][y].nChild=1;
pMe->Cell[x][y].CHILD[0].nx=pMe->PosFind.nx ;
pMe->Cell[x][y].CHILD[0].ny=pMe->PosFind.ny ;
}
else
{
pMe->Cell[pMe->PosFind.nx][pMe->PosFind.ny].CHILD[0].nx=x;
pMe->Cell[pMe->PosFind.nx][pMe->PosFind.ny].CHILD[0].ny=y;
pMe->Cell[pMe->PosFind.nx][pMe->PosFind.ny].nChild=1;
}
x1=pMe->nSelx;
y1=pMe->nSely;
while((x1!=pMe->nAimx)||(y1!=pMe->nAimy))
{
if((pMe->Cell[x1][y1].CHILD[0].nx==x1)&&(pMe->Cell[x1][y1].CHILD[0].ny==y1))
{
break;
}
nChildx=pMe->Cell[x1][y1].CHILD[0].nx;
nChildy=pMe->Cell[x1][y1].CHILD[0].ny;
m=pMe->Cell[x1][y1].CHILD[0].nx;
n=pMe->Cell[x1][y1].CHILD[0].ny;
x1=m;
y1=n;
}
}
///
void PathToSel(AIGoogleApp * pMe,int x,int y,boolean bAim)
{
//转过去的是找到点的准父 接点了.但目前尚无父子关系.
int m,n;
if(bAim)//在目标集中找到的话
{
//指向选择者的.
while(pMe->Cell[x][y].Father.nx!=NOVALUE)
{
m=pMe->Cell[x][y].Father.nx;
n=pMe->Cell[x][y].Father.ny;
pMe->Cell[m][n].CHILD[0].nx=x;
pMe->Cell[m][n].CHILD[0].ny=y;
pMe->Cell[m][n].nChild=1;
x=m;
y=n;
}
}
else
{
x=pMe->PosFind.nx;
y=pMe->PosFind.ny;
while(pMe->Cell[x][y].Father.nx!=NOVALUE)
{
m=pMe->Cell[x][y].Father.nx;
n=pMe->Cell[x][y].Father.ny;
pMe->Cell[m][n].CHILD[0].nx=x;
pMe->Cell[m][n].CHILD[0].ny=y;
pMe->Cell[m][n].nChild=1;
x=m;
y=n;
}
}
}
void PathToAim(AIGoogleApp * pMe,int x,int y,boolean bAim)
{
//转过去的是找到点的准父 接点了.但目前尚无父子关系.
int m,n;
if(bAim)
{
//指向选择者的.
x=pMe->PosFind.nx;
y=pMe->PosFind.ny;
while(pMe->Cell[x][y].Father.nx!=NOVALUE)
{
m=pMe->Cell[x][y].Father.nx;
n=pMe->Cell[x][y].Father.ny;
pMe->Cell[x][y].CHILD[0].nx=m;
pMe->Cell[x][y].CHILD[0].ny=n;
pMe->Cell[x][y].nChild=1;
x=m;
y=n;
}
}
else
{
while(pMe->Cell[x][y].Father.nx!=NOVALUE)
{
m=pMe->Cell[x][y].Father.nx;
n=pMe->Cell[x][y].Father.ny;
pMe->Cell[x][y].CHILD[0].nx=m;
pMe->Cell[x][y].CHILD[0].ny=n;
pMe->Cell[x][y].nChild=1;
x=m;
y=n;
}
}
}