www.gusucode.com > C++九宫格数码游戏源码-源码程序 > C++九宫格数码游戏源码-源码程序\code\JiuG.cpp
//Download by http://www.NewXing.com // JiuG.cpp: implementation of the CJiuG class. #include "stdafx.h" #include "Jiugong.h" #include "JiuG.h" #include "math.h"//计算估价函数是会用到abs(),如果用错位数,则不用包含 #include "stdlib.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CJiuG::CJiuG() { m_ndepth=100;//设置默认的深度为100,可以在程序中改动 } CJiuG::~CJiuG() { } ///////////////////////////////////////////////////////////////////// //左移 bool CJiuG::MoveLeft(JGState *src,JGState *result) { int x,y,tempx,tempy; for(x=0;x<3;x++){ for(y=0;y<3;y++){ if(src->state[x][y]==0){ tempx=x; tempy=y; } } } if(tempy==0) return false; for(int i=0;i<3;i++){ for(int j=0;j<3;j++){ result->state[i][j]=src->state[i][j]; } } result->state[tempx][tempy] = src->state[tempx][tempy-1]; result->state[tempx][tempy-1] = 0; result->curdistance=src->curdistance+1; result->prestate=src; result->nextstate=NULL; return true; } //////////////////////////////////////////////////////////////////// //右移 bool CJiuG::MoveRight(JGState *src,JGState *result) { int x,y,tempx,tempy; for(x=0;x<3;x++){ for(y=0;y<3;y++){ if(src->state[x][y]==0){ tempx=x; tempy=y; } } } if(tempy==2) return false; for(int i=0;i<3;i++){ for(int j=0;j<3;j++){ result->state[i][j]=src->state[i][j]; } } result->state[tempx][tempy]=src->state[tempx][tempy+1]; result->state[tempx][tempy+1]=0; result->curdistance=src->curdistance+1; result->prestate=src; result->nextstate=NULL; return true; } /////////////////////////////////////////////////////////////////// //上移,上面的左移,右移,下面的下移,结构一样 bool CJiuG::MoveUp(JGState *src,JGState *result) { int x,y,tempx,tempy; //寻找空格位置 for(x=0;x<3;x++){ for(y=0;y<3;y++){ if(src->state[x][y]==0){ tempx=x; tempy=y; } } } //判断是否可移 if(tempx==0) return false; for(int i=0;i<3;i++){ for(int j=0;j<3;j++){ result->state[i][j]=src->state[i][j]; } } result->state[tempx][tempy]=src->state[tempx-1][tempy]; result->state[tempx-1][tempy]=0; result->curdistance=src->curdistance+1;//深度加一 result->prestate=src;//设置前趋节点 result->nextstate=NULL; return true; } //////////////////////////////////////////////////////////////////// //下移 bool CJiuG::MoveDown(JGState *src,JGState *result) { int x,y,tempx,tempy; for(x=0;x<3;x++){ for(y=0;y<3;y++){ if(src->state[x][y]==0){ tempx=x; tempy=y; } } } if(tempx==2) return false; for(int i=0;i<3;i++){ for(int j=0;j<3;j++){ result->state[i][j]=src->state[i][j]; } } result->state[tempx][tempy]=result->state[tempx+1][tempy]; result->state[tempx+1][tempy]=0; result->curdistance=src->curdistance+1; result->prestate=src; result->nextstate=NULL; return true; } /////////////////////////////////////////////////////////////////// //比较两个状态是否相等 bool CJiuG::Compare(JGState *src1,JGState *src2) { for(int i=0;i<=2;i++){ for(int j=0;j<=2;j++){ if(src1->state[i][j]!=src2->state[i][j]) return false; } } return true; } /////////////////////////////////////////////////////////////////// //计算估价函数,采用了每一步移到正确的位置需要的步数 int CJiuG::ComputeFn(JGState *cur,JGState *dest) { int xcur[9],ycur[9],xdest[9],ydest[9];//保存9个坐标 int i,j; int result=0; for(i=0;i<3;i++){ for(j=0;j<3;j++){ xcur[cur->state[i][j]]=i; ycur[cur->state[i][j]]=j; xdest[dest->state[i][j]]=i; ydest[dest->state[i][j]]=j; } } for(i=1;i<9;i++){ result=result+abs(xcur[i]-xdest[i])+abs(ycur[i]-ydest[i]); } return result; /*int result=0;//注释掉的部分是采用了错位数来计算 int i,j; for(i=0;i<3;i++){ for(j=0;j<3;j++){ if(cur->state[i][j]!=dest->state[i][j]) result++; } } return result;*/ } /////////////////////////////////////////////////////////////////// //搜索最优解,这是程序的核心部分 bool CJiuG::Search() { int MAXDEPTH=m_ndepth; FreeList(&OpenList); FreeList(&CloseList); FreeList(&ResultList); JGState *newstate,*pstart; int i,k; newstate=(JGState *)malloc(sizeof(JGState)); CopyJG(&StateInit,newstate); newstate->curdistance=0; newstate->nextstate=NULL; newstate->prestate=NULL; pstart=newstate; curstep=pstart; //如果初始状态和末态相同,搜索成功退出 if(Compare(&StateInit,&StateObj)==true){ ResultList.AddTail((void *)newstate); return true; } //将起始结点加入Open表中 OpenList.AddHead((void *)newstate); //搜索 while(true){ JGState *pmin; int nmin; int nindex=0; //Open表为空,失败退出 if(OpenList.IsEmpty()) return false; i=OpenList.GetCount(); nmin=100000000; //搜索Open表中估计值最小的节点 for(k=0;k<i;k++){ JGState *ptemp; ptemp=(JGState *)OpenList.GetAt(OpenList.FindIndex(k)); int ntemp=ptemp->curdistance+ComputeFn(ptemp,&StateObj); if(ntemp<nmin){ nmin=ntemp; pmin=ptemp; nindex=k; } } //将估价函数最小的节点从Open表删除,加入到Close表中 OpenList.RemoveAt(OpenList.FindIndex(nindex)); CloseList.AddTail((void *)pmin); newstate=(JGState *)malloc(sizeof(JGState)); //move to left,用了搜索深度控制。下面的右移,上移,下移程序结构相同 //可以将相同的部分写成函数,我没有这样做 if((MoveLeft(pmin,newstate)==true)&&(newstate->curdistance<=MAXDEPTH)){ if((Compare(newstate,&StateObj)==false)){ //不是目标节点,则看是否可以加入到Open表中 bool inopen=false; bool inclose=false; JGState *ptemp; //检查是否在Open表中 i=OpenList.GetCount(); if(i==0) inopen=false; else{ for(k=0;k<i;k++){ ptemp=(JGState *)OpenList.GetAt(OpenList.FindIndex(k)); if(Compare(newstate,ptemp)==true){ inopen=true; if(ptemp->curdistance>newstate->curdistance) CopyJG(newstate,ptemp); break; } } } //检查是否在Close表中 i=CloseList.GetCount(); if(i==0) inclose=false; else{ for(k=0;k<i;k++){ ptemp=(JGState *)CloseList.GetAt(CloseList.FindIndex(k)); if(Compare(newstate,ptemp)==true){ inclose=true; break; } } } if((inopen==false)&&(inclose==false)) OpenList.AddHead(newstate); }//end if else{ //找到目标结点 JGState *newstate1; ResultList.AddHead((void *)newstate); newstate=newstate->prestate; //回溯,得到ResultList while(newstate!=pstart){ newstate1=(JGState *)malloc(sizeof(JGState)); CopyJG(newstate,newstate1); ResultList.AddHead(newstate1); newstate=newstate->prestate; } newstate1=(JGState *)malloc(sizeof(JGState)); CopyJG(newstate,newstate1); ResultList.AddHead(newstate1); return true; }//end else }//end if else{ free(newstate); }//end move left newstate=(JGState *)malloc(sizeof(JGState)); //move to right if(MoveRight(pmin,newstate)==true&&(newstate->curdistance<=MAXDEPTH)){ if((Compare(newstate,&StateObj)==false)){ //不是目标节点,则看是否可以加入到Open表中 bool inopen=false; bool inclose=false; JGState *ptemp; i=OpenList.GetCount(); if(i==0) inopen=false; else{ for(k=0;k<i;k++){ ptemp=(JGState *)OpenList.GetAt(OpenList.FindIndex(k)); if(Compare(newstate,ptemp)==true){ inopen=true; if(ptemp->curdistance>newstate->curdistance) CopyJG(newstate,ptemp); break; } } } i=CloseList.GetCount(); if(i==0) inclose=false; else{ for(k=0;k<i;k++){ ptemp=(JGState *)CloseList.GetAt(CloseList.FindIndex(k)); if(Compare(newstate,ptemp)==true){ inclose=true; break; } } } if((inopen==false)&&(inclose==false)) OpenList.AddHead(newstate); }//end if else{ //找到目标结点 JGState *newstate1; ResultList.AddHead((void *)newstate); newstate=newstate->prestate; while(newstate!=pstart){ newstate1=(JGState *)malloc(sizeof(JGState)); CopyJG(newstate,newstate1); ResultList.AddHead(newstate1); newstate=newstate->prestate; } newstate1=(JGState *)malloc(sizeof(JGState)); CopyJG(newstate,newstate1); ResultList.AddHead(newstate1); return true; }//end else }//end if else{ free(newstate); }//end move right newstate=(JGState *)malloc(sizeof(JGState)); //move to up if(MoveUp(pmin,newstate)==true&&(newstate->curdistance<=MAXDEPTH)){ if((Compare(newstate,&StateObj)==false)){ //不是目标节点,则看是否可以加入到Open表中 bool inopen=false; bool inclose=false; JGState *ptemp; i=OpenList.GetCount(); if(i==0) inopen=false; else{ for(k=0;k<i;k++){ ptemp=(JGState *)OpenList.GetAt(OpenList.FindIndex(k)); if(Compare(newstate,ptemp)==true){ inopen=true; if(ptemp->curdistance>newstate->curdistance) CopyJG(newstate,ptemp); break; } } } i=CloseList.GetCount(); if(i==0) inclose=false; else{ for(k=0;k<i;k++){ ptemp=(JGState *)CloseList.GetAt(CloseList.FindIndex(k)); if(Compare(newstate,ptemp)==true){ inclose=true; break; } } } if((inopen==false)&&(inclose==false)) OpenList.AddHead(newstate); }//end if else{ //找到目标结点 JGState *newstate1; ResultList.AddHead((void *)newstate); newstate=newstate->prestate; while(newstate!=pstart){ newstate1=(JGState *)malloc(sizeof(JGState)); CopyJG(newstate,newstate1); ResultList.AddHead(newstate1); newstate=newstate->prestate; } newstate1=(JGState *)malloc(sizeof(JGState)); CopyJG(newstate,newstate1); ResultList.AddHead(newstate1); return true; }//end else }//end if else{ free(newstate); }//end move up newstate=(JGState *)malloc(sizeof(JGState)); //move to down if(MoveDown(pmin,newstate)==true&&(newstate->curdistance<=MAXDEPTH)){ if((Compare(newstate,&StateObj)==false)){ //不是目标节点,则看是否可以加入到Open表中 bool inopen=false; bool inclose=false; JGState *ptemp; i=OpenList.GetCount(); if(i==0) inopen=false; else{ for(k=0;k<i;k++){ ptemp=(JGState *)OpenList.GetAt(OpenList.FindIndex(k)); if(Compare(newstate,ptemp)==true){ inopen=true; if(ptemp->curdistance>newstate->curdistance) CopyJG(newstate,ptemp); break; } } } i=CloseList.GetCount(); if(i==0) inclose=false; else{ for(k=0;k<i;k++){ ptemp=(JGState *)CloseList.GetAt(CloseList.FindIndex(k)); if(Compare(newstate,ptemp)==true){ inclose=true; break; } } } if((inopen==false)&&(inclose==false)) OpenList.AddHead(newstate); }//end if else{ //找到目标结点 JGState *newstate1; ResultList.AddHead((void *)newstate); newstate=newstate->prestate; while(newstate!=pstart){ newstate1=(JGState *)malloc(sizeof(JGState)); CopyJG(newstate,newstate1); ResultList.AddHead(newstate1); newstate=newstate->prestate; } newstate1=(JGState *)malloc(sizeof(JGState)); CopyJG(newstate,newstate1); ResultList.AddHead(newstate1); return true; }//end else }//end if else{ free(newstate); }//end move down } } /////////////////////////////////////////////////////////////////// //释放内存 void CJiuG::FreeList(CPtrList *list) { if(list->IsEmpty()) return; int i=list->GetCount(); JGState *p; for(int j=0;j<i;j++){ p=(JGState *)list->GetHead(); list->RemoveHead(); free(p); } } void CJiuG::CopyJG(JGState *src,JGState *dest) { for(int i=0;i<3;i++){ for(int j=0;j<3;j++){ dest->state[i][j]=src->state[i][j]; } } dest->curdistance=src->curdistance; dest->prestate=src->prestate; dest->nextstate=src->nextstate; } ////////////////////////////////////////////////////////////////// //计算逆序奇偶性,以判断有无解,基于我对九宫问题解是否可达的证明 //返回0为偶,返回1为奇 int CJiuG::ComputeJO(JGState *jo) { int result=0; int i,j; int k=0; int temp[8]; //除去0,将其余8个数依次加入到数组中 for(i=0;i<3;i++){ for(j=0;j<3;j++){ if(jo->state[i][j]!=0){ temp[k]=jo->state[i][j]; k++; } } } //判断奇偶性 for(i=0;i<7;i++){ for(j=i+1;j<8;j++){ if(temp[i]>temp[j]) result++; } } result=result%2; return result; }