转载请注明出处:http://hi.baidu.com/lvchengbin405/blog/item/e354fd1faaeb09c0a7866921.html
// 类的定义头文件EDCPP.h #include <stdio.h> #include <stdlib.h> #ifndef _EDCPP_H #define _EDCPP_H struct State{ char value[3][3]; int blankx; // blank position x int blanky; // blank position y }; class EDCNode{ private: int m_index; // ID State* m_state; // state int m_g; // g value int m_h; // h value int m_x; // x coordinate(for drawing) int m_y; // y coordinate(for drawing) int m_parent; public: // 构造与析构函数 EDCNode(); EDCNode(EDCNode& node); ~EDCNode(); // 初始化Node void InitEDCNode(int index, State* s); void InitEDCNode(int index, State* s, int x, int y); void InitEDCNode(int index, State* s, int g, int h, int x, int y); // Set函数 void SetIndex(const int index); void SetState(State* s); void SetG(const int g); void SetH(const int h); void SetX(const int x); void SetY(const int y); void SetParent(int parentindex); // Get函数 int GetIndex(); State* GetState(); int GetG(); int GetH(); int GetF(); int GetX(); int GetY(); int GetParent(); // 静态函数,由类调用 static bool MoveLeft(State* s); // 左移,返回值false表示不可移 static bool MoveRight(State* s); // 右移,返回值false表示不可移 static bool MoveUp(State* s); // 上移,返回值false表示不可移 static bool MoveDown(State* s); // 下移,返回值false表示不可移 static bool Compare(State* s1, State* s2); // 比较两种状态是否一样,返回值false表示不一样 }; #define MAXNUM 100 #define EDC_L 1 #define EDC_R 2 #define EDC_U 3 #define EDC_D 4 class EDC { private: static int m_index;// EDCNode* m_start; // 起始节点 EDCNode* m_end; // 目标节点 EDCNode m_openList[MAXNUM]; // Open表 EDCNode m_closeList[MAXNUM]; // Close表 int m_openNum; // Open表节点个数 int m_closeNum; // Close表节点个数 int m_gParas; // 值为1时选择g(suc)=g(bes)+h(suc,bes),为0时选择g(child)=g(parent)+1 int m_hParasDn; // h(scr,des)=aDn+bPn+cSn,Dn方法的系数a int m_hParasPn; // h(scr,des)=aDn+bPn+cSn,Pn方法的系数b int m_hParasSn; // h(scr,des)=aDn+bPn+cSn,Sn方法的系数c public: // 构造函数 EDC(); // 构造函数2,具备起始节点和目标节点和代价树参数 EDC(EDCNode* start, EDCNode* end, int g, int hd, int hp, int hs); // 析构函数 ~EDC(); EDCNode* GetStart(); EDCNode* GetEnd(); int GetOpenNum(); int GetCloseNum(); EDCNode* GetNodeFromOpenList(int index); EDCNode* GetNodeFromCloseList(int index); void GetParas(int& gParas, int& hParasDn, int& hParasPn, int& hParasSn); void InsertToOpenList(EDCNode* node); // 插入一个节点到Open表中,并构建堆 EDCNode* PopNodeFromOpenList(); // 取Open表首元素,并调整堆 int IsInOpenList(EDCNode* node); // 判断该节点是否在Open表中 void UpdateOpenList(int index); // 更新堆,使第一元素为最小元素 void InsertToCloseList(EDCNode* node); // 插入一个节点到Close表中,按照G值从小到大排序 int IsInCloseList(EDCNode* node); // 判断该节点是否在Close表中 int GetNodeParentFromCloseList(int index); // 获取Close中下标为index的父节点在Close的位置。 EDCNode* ExpandNode(EDCNode* node, int direct); // 扩展子节点 void SetParas(int g, int hd, int hp, int hs); // 设置代价树参数 int CalculateG(EDCNode* node1, EDCNode* node2); // 计算节点的G值,由m_gParas决定计算方式 int CalculateH(EDCNode* node1, EDCNode* node2); // 计算节点1到节点2的H值,h(scr,des)=aDn+bPn+cSn static int DnMethod(EDCNode* node1, EDCNode* node2); // D(n)表示节点node1的格局与node2目标节点格局的不同牌数,包括空格 static int PnMethod(EDCNode* node1, EDCNode* node2); // P(n)是指node1格局各将牌离“家”(node2)的最短路径之和,包括空格 static int SnMethod(EDCNode* node1, EDCNode* node2); /* S(n)计算方法:依照顺时针方向来检查非中心位置的每个奖牌, 若其后紧跟的将牌与目标格局一致,该将牌得0分,否则得2分; 中间方格有将牌得1分,否则得0分。所有将牌得分之和即为S(n)。*/ void StartEDC(); // 启动EDC,为单步遍历做好准备 int EDCOnce(); // 遍历搜索树一次,返回值-1表示失败,0表示继续,1表示成功 bool EDCAll(); // 遍历直到结果出来,返回值ture表示成功,false表示失败 }; #endif; ********************************************************************************************************************* // 类的实现EDCPP.cpp 文件 #include "EDCPP.h" //------------------------------------------------------------------------- // EDCNode class //------------------------------------------------------------------------- EDCNode::EDCNode() { m_index = -1; m_state = new State(); m_g = 0; m_h = 0; m_x = 0; m_y = 0; m_parent = -1; } EDCNode::EDCNode(EDCNode &node) { m_index = node.m_index; m_state = new State(*(node.m_state)); m_g = node.m_g; m_h = node.m_h; m_x = node.m_x; m_y = node.m_y; m_parent = node.m_parent; } EDCNode::~EDCNode() { m_index = -1; if (!m_state) delete m_state; m_state = NULL; m_g = 0; m_h = 0; m_x = 0; m_y = 0; } void EDCNode::InitEDCNode(int index, State* s) { m_index = index; *m_state = *s; } void EDCNode::InitEDCNode(int index, State* s, int x, int y) { m_index = index; *m_state = *s; m_x = x; m_y = y; } void EDCNode::InitEDCNode(int index, State* s, int g, int h, int x, int y) { m_index = index; *m_state = *s; m_g = g; m_h = h; m_x = x; m_y = y; } void EDCNode::SetIndex(const int index) { m_index = index; } void EDCNode::SetState(State* s) { m_state = s; } void EDCNode::SetG(const int g) { m_g = g; } void EDCNode::SetH(const int h) { m_h = h; } void EDCNode::SetX(const int x) { m_x = x; } void EDCNode::SetY(const int y) { m_y = y; } void EDCNode::SetParent(int parentindex) { m_parent = parentindex; } int EDCNode::GetIndex() { return m_index; } State* EDCNode::GetState() { return m_state; } int EDCNode::GetG() { return m_g; } int EDCNode::GetH() { return m_h; } int EDCNode::GetF() { return m_g + m_h; } int EDCNode::GetX() { return m_x; } int EDCNode::GetY() { return m_y; } int EDCNode::GetParent() { return m_parent; } bool EDCNode::MoveLeft(State* s) { if (s->blanky==0) return false; s->value[s->blankx][s->blanky] = s->value[s->blankx][s->blanky-1]; s->blanky--; s->value[s->blankx][s->blanky] = '0'; return true; } bool EDCNode::MoveRight(State* s) { if (s->blanky==2) return false; s->value[s->blankx][s->blanky] = s->value[s->blankx][s->blanky+1]; s->blanky++; s->value[s->blankx][s->blanky] = '0'; return true; } bool EDCNode::MoveUp(State* s) { if (s->blankx==0) return false; s->value[s->blankx][s->blanky] = s->value[s->blankx-1][s->blanky]; s->blankx--; s->value[s->blankx][s->blanky] = '0'; return true; } bool EDCNode::MoveDown(State* s) { if (s->blankx==2) return false; s->value[s->blankx][s->blanky] = s->value[s->blankx+1][s->blanky]; s->blankx++; s->value[s->blankx][s->blanky] = '0'; return true; } bool EDCNode::Compare(State* s1, State* s2) { for (int i=0; i<3; i++) for (int j=0; j<3; j++) { if (s1->value[i][j] != s2->value[i][j]) return false; } return true; } //------------------------------------------------------------------------- // EDC class //------------------------------------------------------------------------- int EDC::m_index = 0; EDC::EDC() { m_start = new EDCNode(); m_end = new EDCNode(); m_openNum = 0; m_closeNum = 0; m_gParas = 0; m_hParasDn = 1; m_hParasPn = 0; m_hParasSn = 0; } EDC::EDC(EDCNode* start, EDCNode* end, int g=0, int hd=1, int hp=0, int hs=0) { m_start = new EDCNode(*start); m_end = new EDCNode(*end); m_openNum = 0; m_closeNum = 0; m_gParas = g; m_hParasDn = hd; m_hParasPn = hp; m_hParasSn = hs; } EDC::~EDC() { if (m_start) delete m_start; if (m_end) delete m_end; m_start = NULL; m_end = NULL; m_openNum = 0; m_closeNum = 0; m_gParas = 0; m_hParasDn = 1; m_hParasPn = 0; m_hParasSn = 0; } EDCNode* EDC::GetStart() { return m_start; } EDCNode* EDC::GetEnd() { return m_end; } int EDC::GetOpenNum() { return m_openNum; } int EDC::GetCloseNum() { return m_closeNum; } EDCNode* EDC::GetNodeFromOpenList(int index) { if (index<1 || index>m_openNum) return NULL; return &m_openList[index]; } EDCNode* EDC::GetNodeFromCloseList(int index) { if (index<1 || index>m_closeNum) return NULL; return &m_closeList[index]; } void EDC::GetParas(int &gParas, int &hParasDn, int &hParasPn, int &hParasSn) { gParas = m_gParas; hParasDn = m_hParasDn; hParasPn = m_hParasPn; hParasSn = m_hParasSn; } void EDC::InsertToOpenList(EDCNode* node) { m_openList[++m_openNum] = *node; UpdateOpenList(m_openNum); } EDCNode* EDC::PopNodeFromOpenList() { if (m_openNum<1) return NULL; // 获取首元素 EDCNode* node = new EDCNode(m_openList[1]); // 调整堆 m_openList[1] = m_openList[m_openNum--]; int u,v=1; EDCNode temp; do { u = v; if (u*2+1<=m_openNum) { if (m_openList[u].GetF()>=m_openList[u*2].GetF()) v = u*2; if (m_openList[v].GetF()>=m_openList[u*2+1].GetF()) v = u*2+1; } else if (u*2<=m_openNum) { if (m_openList[u].GetF()>=m_openList[u*2].GetF()) v = u*2; } if (u==v) break; else { temp = m_openList[u]; m_openList[u] = m_openList[v]; m_openList[v] = temp; } }while (true); return node; } int EDC::IsInOpenList(EDCNode* node) { for (int i=0; i<m_openNum; i++) { if (EDCNode::Compare(node->GetState(), m_openList[i].GetState())) return i; } return -1; } void EDC::UpdateOpenList(int index) { if (index<1 || index>m_openNum) return; EDCNode temp; int i = index; while (i!=1) { if (m_openList[i].GetF() <= m_openList[i/2].GetF()) { temp = m_openList[i/2]; m_openList[i/2] = m_openList[i]; m_openList[i] = temp; i = i/2; } else break; } } void EDC::InsertToCloseList(EDCNode* node) { //m_closeList[++m_closeNum] = *node; int i; for (i=m_closeNum; i>0; i--) { if (m_closeList[i].GetG() > node->GetG()) { m_closeList[i+1] = m_closeList[i]; } else { break; } } m_closeList[i+1] = *node; m_closeNum++; } int EDC::IsInCloseList(EDCNode* node) { for (int i=0; i<m_closeNum; i++) { if (EDCNode::Compare(node->GetState(), m_closeList[i].GetState())) return i; } return -1; } int EDC::GetNodeParentFromCloseList(int index) { if (index>m_closeNum) return -1; for (int i=0; i<index; i++) { if (m_closeList[index].GetParent() == m_closeList[i].GetIndex()) return i; } return -1; } EDCNode* EDC::ExpandNode(EDCNode* node, int direct) { EDCNode* child = new EDCNode(*node); bool result = false; switch (direct) { case EDC_L: if (EDCNode::MoveLeft(child->GetState())) result = true; break; case EDC_R: if (EDCNode::MoveRight(child->GetState())) result = true; break; case EDC_U: if (EDCNode::MoveUp(child->GetState())) result = true; break; case EDC_D: if (EDCNode::MoveDown(child->GetState())) result = true; break; default: result = false; } if (result) { child->SetIndex(++EDC::m_index); return child; } delete child; return NULL; } void EDC::SetParas(int g, int hd, int hp, int hs) { m_gParas = g; m_hParasDn = hd; m_hParasPn = hp; m_hParasSn = hs; } int EDC::CalculateG(EDCNode* node1, EDCNode* node2) { int res; if (m_gParas==1) res = node1->GetG() + CalculateH(node1, node2); else if (m_gParas==0) res = node1->GetG() + 1; else res = 0; return res; } int EDC::CalculateH(EDCNode* node1, EDCNode* node2) { int res = 0; if (m_hParasDn != 0) res += m_hParasDn*DnMethod(node1, node2); if (m_hParasPn != 0) res += m_hParasPn*PnMethod(node1, node2); if (m_hParasSn != 0) res += m_hParasSn*SnMethod(node1, node2); return res; } int EDC::DnMethod(EDCNode *node1, EDCNode *node2) { State *s1 = node1->GetState(); State *s2 = node2->GetState(); int i,j, Dn=0; for (i=0; i<3; i++) { for (j=0; j<3; j++) { if (s1->value[i][j] != s2->value[i][j]) Dn++; } } return Dn; } int EDC::PnMethod(EDCNode *node1, EDCNode *node2) { State *s1 = node1->GetState(); State *s2 = node2->GetState(); int xcur[9], ycur[9], xdes[9], ydes[9]; int i,j, Pn=0; for (i=0; i<3; i++) { for (j=0; j<3; j++) { xcur[s1->value[i][j] - '0'] = i; ycur[s1->value[i][j] - '0'] = j; xdes[s2->value[i][j] - '0'] = i; ydes[s2->value[i][j] - '0'] = j; } } for (i=0; i<9; i++) { Pn += abs(xdes[i]-xcur[i]) + abs(ydes[i]-ycur[i]); } return Pn; } int EDC::SnMethod(EDCNode *node1, EDCNode *node2) { State *s1 = node1->GetState(); State *s2 = node2->GetState(); int i, k, Sn=0; int dirX[9]; int dirY[9]; if (s2->blankx==0) { if (s2->blanky==0) { dirX[0]=0;dirX[1]=0;dirX[2]=1;dirX[3]=2; dirX[4]=2;dirX[5]=2;dirX[6]=1;dirX[7]=1;dirX[8]=0; dirY[0]=1;dirY[1]=2;dirY[2]=2;dirY[3]=2; dirY[4]=1;dirY[5]=0;dirY[6]=0;dirY[7]=1;dirY[8]=1; } else if (s2->blanky==1) { dirX[0]=0;dirX[1]=1;dirX[2]=2;dirX[3]=2; dirX[4]=2;dirX[5]=1;dirX[6]=0;dirX[7]=1;dirX[8]=0; dirY[0]=2;dirY[1]=2;dirY[2]=2;dirY[3]=1; dirY[4]=0;dirY[5]=0;dirY[6]=0;dirY[7]=1;dirY[8]=2; } else // blanky=2 { dirX[0]=1;dirX[1]=2;dirX[2]=2;dirX[3]=2; dirX[4]=1;dirX[5]=0;dirX[6]=0;dirX[7]=1;dirX[8]=1; dirY[0]=2;dirY[1]=2;dirY[2]=1;dirY[3]=0; dirY[4]=0;dirY[5]=0;dirY[6]=1;dirY[7]=1;dirY[8]=2; } } else if (s2->blankx==1) { if (s2->blanky==0) { dirX[0]=0;dirX[1]=0;dirX[2]=0;dirX[3]=1; dirX[4]=2;dirX[5]=2;dirX[6]=2;dirX[7]=1;dirX[8]=0; dirY[0]=0;dirY[1]=1;dirY[2]=2;dirY[3]=2; dirY[4]=2;dirY[5]=1;dirY[6]=0;dirY[7]=1;dirY[8]=0; } else if (s2->blanky==1) { dirX[0]=0;dirX[1]=0;dirX[2]=0;dirX[3]=1; dirX[4]=2;dirX[5]=2;dirX[6]=2;dirX[7]=1;dirX[8]=0; dirY[0]=0;dirY[1]=1;dirY[2]=2;dirY[3]=2; dirY[4]=2;dirY[5]=1;dirY[6]=0;dirY[7]=0;dirY[8]=0; } else // blanky=2 { dirX[0]=2;dirX[1]=2;dirX[2]=2;dirX[3]=1; dirX[4]=0;dirX[5]=0;dirX[6]=0;dirX[7]=1;dirX[8]=2; dirY[0]=2;dirY[1]=1;dirY[2]=0;dirY[3]=0; dirY[4]=0;dirY[5]=1;dirY[6]=2;dirY[7]=1;dirY[8]=2; } } else // blankx=2 { if (s2->blanky==0) { dirX[0]=1;dirX[1]=0;dirX[2]=0;dirX[3]=0; dirX[4]=1;dirX[5]=2;dirX[6]=2;dirX[7]=1;dirX[8]=1; dirY[0]=0;dirY[1]=0;dirY[2]=1;dirY[3]=2; dirY[4]=2;dirY[5]=2;dirY[6]=1;dirY[7]=1;dirY[8]=0; } else if (s2->blanky==1) { dirX[0]=2;dirX[1]=1;dirX[2]=0;dirX[3]=0; dirX[4]=0;dirX[5]=1;dirX[6]=2;dirX[7]=1;dirX[8]=2; dirY[0]=0;dirY[1]=0;dirY[2]=0;dirY[3]=1; dirY[4]=2;dirY[5]=2;dirY[6]=2;dirY[7]=1;dirY[8]=0; } else // blanky=2 { dirX[0]=2;dirX[1]=2;dirX[2]=1;dirX[3]=0; dirX[4]=0;dirX[5]=0;dirX[6]=1;dirX[7]=1;dirX[8]=2; dirY[0]=1;dirY[1]=0;dirY[2]=0;dirY[3]=0; dirY[4]=1;dirY[5]=2;dirY[6]=2;dirY[7]=1;dirY[8]=1; } } for (k=0; k<8; k++) { for (i=0; i<8; i++) { if (s1->value[dirX[k]][dirY[k]] == s2->value[dirX[i]][dirY[i]]) { if (s1->value[dirX[k+1]][dirY[k+1]] != s2->value[dirX[i+1]][dirY[i+1]]) { Sn += 2; break; } break; } } } if (s1->blankx!=s2->blankx || s1->blanky!=s2->blanky) Sn += 1; return Sn; } int EDC::EDCOnce() { // 选取open表中未设置过的具有最小f值的节点bestnode EDCNode* bestnode = PopNodeFromOpenList(); if (!bestnode) return -1; // open表为空,返回-1,失败 // 放入close表 InsertToCloseList(bestnode); // 判断bestnode是否是目标节点,如果是返回1,成功 if (EDCNode::Compare(bestnode->GetState(), m_end->GetState())) return 1; // 扩展bestnode,从4个移动方向产生其后续节点successor int i=EDC_L; int old = -1; EDCNode* successor; while(i<=EDC_D) { successor = ExpandNode(bestnode, i); i++; if (!successor) continue; // 建立从successor返回bestnode的指针 successor->SetParent(bestnode->GetIndex()); /*// 计算个g(suc)=g(bes)+h(bes,suc) successor->SetG(CalculateG(bestnode, successor));*/ // 计算个g(suc)=g(bes)+1,深度加1 successor->SetG(CalculateG(bestnode, successor)); // suc是否在openlist中,如果在则返回位置 old = IsInOpenList(successor); if (old!=-1) { // 判断g(suc)<g(old) if (successor->GetG()<m_openList[old].GetG()) { // 重新确定old的父辈节点为bestnode,并修正父辈节点的g值 m_openList[old].SetParent(bestnode->GetIndex()); m_openList[old].SetG(successor->GetG()); } } else // 不在openlist中 { // 如果不在closelist表中 if (IsInCloseList(successor)==-1) { // 计算H值 successor->SetH(CalculateH(successor, m_end)); InsertToOpenList(successor); // 放入openlist中 } } delete successor; } delete bestnode; return 0; // 继续 } bool EDC::EDCAll() { InsertToOpenList(m_start); int result=0; while (result==0) { result = EDCOnce(); } if (result==-1) return false; return true; } void EDC::StartEDC() { m_openNum = 0; m_closeNum = 0; m_index = 0; InsertToOpenList(m_start); }