雪漫群吧 关注:12贴子:580
  • 12回复贴,共1
//用A*算法实现八数码问题
// 如:2 8 3         1 2 3          //0-2行,0-2列
//     1 6 4 ------》8   4
//     7   5         7 6 5
//A*算法,即设h为在位的数字个数,只有当h*<=h时才向下拓展
//重复以前动作为非法操作
#include<iostream.h>
#include<math.H >
#include<stdlib.h>   //异常处理
class MatrixNode{
public:   
  int w;               //不在位
  int h;               //牌与其目标位置直接步数之和
  int g;               //已经走的步数
  int m;               //在位的数字个数
  int p;               //牌与其目标位置直接步数之和
  int f;               //h+g
  int place[3][3];     //当前矩阵
      int placetrue[3][3];  //正确矩阵
      int zeroplace[3][3];  //全0矩阵,移动时若为全零矩阵则移动无效
  int kong_x;  //空位的横坐标
      int kong_y;  //空位的纵坐标
//-------------------------------------------------------------------------------
  public:
  MatrixNode();
  MatrixNode fuzhi(MatrixNode M_Matrix);  //给第一个矩阵赋值;
  int TruePlace(MatrixNode T_place );     // 查找在位数
  int N_TruePlace(MatrixNode N_place );   // 查找在不位数
  int p_place(MatrixNode P_place);       //牌与其目标位置直接步数之和(坐标差之和为距离)
  void printMatrix(const int Pri_Matrix[][3] );//输出矩阵
      int f_kongx(MatrixNode find_kongx);    //找出空位的x坐标
  int f_kongy(MatrixNode find_kongy);     //找出空位的y坐标
  MatrixNode up_move(MatrixNode M_Matrix);   //空格向上移动一格
      MatrixNode down_move(MatrixNode M_Matrix);   //空格向下移动一格
  MatrixNode left_move(MatrixNode M_Matrix);   //空格向左移动一格
      MatrixNode right_move(MatrixNode M_Matrix);   //空格向右移动一格
      MatrixNode updata_m(MatrixNode M_Matrix);   //移动后更新状态
  bool PlaceAndZero(MatrixNode M_Matrix);//判断矩阵是否为零矩阵
  bool mat_jug(MatrixNode M_Matrix1,MatrixNode M_Matrix2); //判断节点中的矩阵是否相同
};



1楼2009-11-26 20:24回复
    //=========================================================================================
    MatrixNode::MatrixNode(){                      //构造函数
            placetrue[0][0] = 1;               //标准矩阵
                placetrue[0][1] = 2;
        placetrue[0][2] = 3;
          placetrue[1][0] = 8;
         placetrue[1][1] = -1;
         placetrue[1][2] = 4;
         placetrue[2][0] = 7;
         placetrue[2][1] = 6;
         placetrue[2][2] = 5;
          for(int a = 0;a <= 2;a++){              //给矩阵赋值
         for(int b = 0;b <= 2;b++ ){
              place[a][b] = 0;
        }
    }
       
         for(int ax = 0;ax <= 2;ax++){             //给零矩阵赋值
          for(int by = 0;by <= 2;by++ ){
         zeroplace[ax][by] = 0;
    }
    }
            
        for(int Pa = 0;Pa <= 2;Pa++){             //找出矩阵空格的横纵坐标
         for(int Pb = 0;Pb <= 2;Pb++){
         if(place[Pa][Pb] == 0){
              kong_x = Pa;
          kong_y = Pb;
     }
     }
    }
        g = 0;       //步数g
    h = 0;
    f = h + g;   //f值
    }
    //-----------------------------------------------------------------------------------------
    MatrixNode MatrixNode::fuzhi(MatrixNode M_Matrix){      //给第一个矩阵赋值
               for(int a = 0;a <= 2;a++){              //给矩阵赋值
         for(int b = 0;b <= 2;b++ ){
              cout<<"请输入坐标为:("<<a<<","<<b<<")存放的数(空位用0表示);";
         cin>>M_Matrix.place[a][b];
         cout<<endl;


    2楼2009-11-26 20:25
    回复
      }
      }
        M_Matrix = M_Matrix.updata_m( M_Matrix);
                M_Matrix.f = M_Matrix.f - 1;// 更新状态时步数加一多余,故减去
        M_Matrix.g = M_Matrix.g - 1;
         return M_Matrix;
      }
      //-----------------------------------------------------------------------------------------
      bool MatrixNode::PlaceAndZero(MatrixNode M_Matrix){       //判断矩阵是否为零矩阵
        for(int a = 0;a <= 2;a++){              //给矩阵赋值
           for(int b = 0;b <= 2;b++ ){
                if(M_Matrix.place[a][b] != 0 ) return false;
          }
        } 
        return true;
      }
      //-----------------------------------------------------------------------------------------
      bool MatrixNode::mat_jug(MatrixNode M_Matrix1,MatrixNode M_Matrix2){ //判断节点中的矩阵是否相同
             for(int a = 0;a <= 2;a++){              //给矩阵赋值
           for(int b = 0;b <= 2;b++ ){
                if(M_Matrix1.place[a][b] != M_Matrix2.place[a][b] ) return false;
          }
         } 
        return true;
      }
      //------------------------------------------------------------------------------------------
      int MatrixNode::TruePlace(MatrixNode T_place ) {              // 查找在位数
            T_place.m = 0;
        int NumT_place = 0;
       
        for(int Ta = 0;Ta <= 2;Ta++){
      for(int Tb = 0;Tb <= 2;Tb++ ){
      if( T_place.place[Ta][Tb] == T_place.placetrue[Ta][Tb]) {
         T_place.m = T_place.m + 1;
      NumT_place = NumT_place + 1;
      }
      }
        }
        return NumT_place;
      }
      //----------------------------------------------------------------------------------
        int MatrixNode::N_TruePlace(MatrixNode N_place ) {              // 查找在不位数
           int NumN_place = 0;


      3楼2009-11-26 20:26
      回复
        N_place.w = 0;
          for(int Na = 0;Na <= 2;Na++){
        for(int Nb = 0;Nb <= 2;Nb++ ){
        if( N_place.place[Na][Nb] != N_place.placetrue[Na][Nb]) {
            N_place.w = N_place.w + 1;
        NumN_place = NumN_place + 1;
        }
        }
          }
               N_place.w = N_place.w - 1;                 // 空位也不在位,需要减去
           NumN_place = NumN_place - 1;
           return NumN_place;
          }
        //-----------------------------------------------------------------------------------
              int MatrixNode::p_place(MatrixNode P_place){                    //牌与其目标位置直接步数之和(坐标差之和为距离)
                  P_place.p = 0;
          int num = 0;
          for(int Pa = 0;Pa <= 2;Pa++){
          for(int Pb = 0;Pb <= 2;Pb++){
          //for(int Pc = 1;Pc <= 8;Pc++){
          if(P_place.place[Pa][Pb] == 1){
                            P_place.p = P_place.p+ (abs(Pa - 0)+abs(Pb - 0));
          }
                          if(P_place.place[Pa][Pb] == 2){
          P_place.p = P_place.p+ (abs(Pa - 0)+abs(Pb - 1));
          }
          if(P_place.place[Pa][Pb] == 3){
          P_place.p = P_place.p+ (abs(Pa - 0)+abs(Pb - 2));
          }
               if(P_place.place[Pa][Pb] == 4){
          P_place.p = P_place.p+ (abs(Pa - 1)+abs(Pb - 2));
          }
          if(P_place.place[Pa][Pb] == 5){
          P_place.p = P_place.p+ (abs(Pa - 2)+abs(Pb - 2));
          }
               if(P_place.place[Pa][Pb] == 6){
          P_place.p = P_place.p+ (abs(Pa - 2)+abs(Pb - 1));
          }
          if(P_place.place[Pa][Pb] == 7){
          P_place.p = P_place.p+ (abs(Pa - 2)+abs(Pb - 0));
          }
          if(P_place.place[Pa][Pb] == 8){
          P_place.p = P_place.p+ (abs(Pa - 1)+abs(Pb - 0));


        4楼2009-11-26 20:26
        回复
          }
           
            }
            }
                num =  P_place.p;
            return num;
            }
          //----------------------------------------------------------------------------------
            int MatrixNode::f_kongx(MatrixNode find_kongx){    //返回空格横坐标
                   int num = 0;
            for(int Pa = 0;Pa <= 2;Pa++){
            for(int Pb = 0;Pb <= 2;Pb++){
            if(find_kongx.place[Pa][Pb] == 0){
                num = Pa;
            }
            }
            }
            return num;
            }
          //-----------------------------------------------------------------------------------
                int MatrixNode::f_kongy(MatrixNode find_kongy){      //返回空格纵坐标
            int num = 0;
            for(int Pa = 0;Pa <= 2;Pa++){
            for(int Pb = 0;Pb <= 2;Pb++){
            if(find_kongy.place[Pa][Pb] == 0){
                num = Pb;
            }
            }
            }
            return num;
            }
          //----------------------------------------------------------------------------------
           MatrixNode MatrixNode::updata_m(MatrixNode M_Matrix){       //移动后更新状态
                
             MatrixNode up_m = M_Matrix; 
             up_m.m = up_m.TruePlace(up_m);     // 查找在位数
             up_m.w = up_m.N_TruePlace(up_m);     // 查找不在位数
             up_m.p = up_m.p_place(up_m);         //距离和
             up_m.kong_x = up_m.f_kongx(up_m);    //找出空位的x坐标
                     up_m.kong_y = up_m.f_kongy(up_m);     //找出空位的y坐标
              up_m.h = up_m.p;
             up_m.g  = up_m.g + 1;            //步数
             up_m.f = up_m.h + up_m.g;        //f值
             return up_m;


          5楼2009-11-26 20:27
          回复
            }
            //-----------------------------------------------------------------------------------
              MatrixNode MatrixNode::up_move(MatrixNode M_Matrix){        //空格向上移动一格
                  int x = 0;
              int num = 0;
             
                      MatrixNode up_m = M_Matrix;
              MatrixNode updata_m = M_Matrix;
             
              x = M_Matrix.kong_x - 1;
              if(x < 0){
                  for(int xx = 0;xx <= 2;xx++){
                 for(int yy = 0;yy <= 2;yy++){
                   up_m.place[xx][yy] = 0;
             }
              }
                  return up_m;
              }
                       num = up_m.place[up_m.kong_x][up_m.kong_y];
                       up_m.place[up_m.kong_x][up_m.kong_y] = up_m.place[up_m.kong_x - 1][up_m.kong_y ];
                       up_m.place[up_m.kong_x - 1][up_m.kong_y ] = num;
                       
               updata_m = MatrixNode::updata_m(up_m);
               return updata_m;
               
              }
            //-----------------------------------------------------------------------------------
             MatrixNode MatrixNode::down_move(MatrixNode M_Matrix){      //空格向下移动一格
                            int x = 0;
              int num = 0;
             
                      MatrixNode up_m = M_Matrix;
              MatrixNode updata_m = M_Matrix;
             
              x = M_Matrix.kong_x + 1;
              if(x > 2){
                  for(int xx = 0;xx <= 2;xx++){
                 for(int yy = 0;yy <= 2;yy++){
                   up_m.place[xx][yy] = 0;
             }
              }


            6楼2009-11-26 20:27
            回复
              return up_m;
                }
                         num = up_m.place[up_m.kong_x][up_m.kong_y];
                         up_m.place[up_m.kong_x][up_m.kong_y] = up_m.place[up_m.kong_x + 1][up_m.kong_y ];
                         up_m.place[up_m.kong_x + 1][up_m.kong_y ] = num;
                         
                 updata_m = MatrixNode::updata_m(up_m);
                 return updata_m;
                  
               }
              //-----------------------------------------------------------------------------------
                    MatrixNode MatrixNode::left_move(MatrixNode M_Matrix){       //空格向左移动一格
                    int y = 0;
                int num = 0;
                MatrixNode up_m = M_Matrix;
                MatrixNode updata_m = M_Matrix;
               
                y = M_Matrix.kong_y - 1;
                if(y < 0){
                    for(int xx = 0;xx <= 2;xx++){
                   for(int yy = 0;yy <= 2;yy++){
                     up_m.place[xx][yy] = 0;
               }
                }
                    return up_m;
                }
                         num = up_m.place[up_m.kong_x][up_m.kong_y];
                         up_m.place[up_m.kong_x][up_m.kong_y] = up_m.place[up_m.kong_x ][up_m.kong_y - 1 ];
                         up_m.place[up_m.kong_x ][up_m.kong_y - 1] = num;
                         
                 updata_m = MatrixNode::updata_m(up_m);
                 return updata_m;
                }
              //-----------------------------------------------------------------------------------
                MatrixNode MatrixNode::right_move(MatrixNode M_Matrix){      //空格向右移动一格
                        int y = 0;
                int num = 0;
               
                        MatrixNode up_m = M_Matrix;
                MatrixNode updata_m = M_Matrix;


              7楼2009-11-26 20:30
              回复
                y = M_Matrix.kong_y + 1;
                  if(y > 2 ){
                      for(int xx = 0;xx <= 2;xx++){
                     for(int yy = 0;yy <= 2;yy++){
                       up_m.place[xx][yy] = 0;
                 }
                  }
                      return up_m;
                  }
                           num = up_m.place[up_m.kong_x][up_m.kong_y];
                           up_m.place[up_m.kong_x][up_m.kong_y] = up_m.place[up_m.kong_x ][up_m.kong_y + 1 ];
                           up_m.place[up_m.kong_x ][up_m.kong_y + 1] = num;
                           updata_m = MatrixNode::updata_m(up_m);
                   return updata_m;
                  }
                //-----------------------------------------------------------------------------------
                //-----------------------------------------------------------------------------------
                  void MatrixNode::printMatrix(const int Pri_Matrix[][3] ){  //输出矩阵
                           for(int a = 0;a <= 2;a++){
                     for(int b = 0;b <= 2;b++ ){
                        cout<<Pri_Matrix[a][b];
                    cout<<" , ";
                }
                        cout<<endl;
                   }
                           cout<<endl;
                  }
                //----------------------------------------------------------------------------------
                //==========================================================================
                class Node{
                  public: 
                  MatrixNode data;
                  Node *link;
                  
                };
                class  Queue{
                   public:
                      int num;   //队列中元素个数
                      Node *front;        //指向头节点指针
                  Node *rear;         // 指向尾节点指针


                8楼2009-11-26 20:31
                回复
                  public:
                     Queue(){
                      front = NULL;
                  rear = NULL; 
                          num = 0;       
                     }
                     ~Queue();
                     void add(MatrixNode Matrix); //入队
                     MatrixNode putout();         //出队
                     bool lookover(MatrixNode Matrix);   //查看是否有相同项,
                     
                  };
                  //=========================================================================
                   Queue::~Queue(){
                      Node *next;
                  while(front){
                       next = front->link;
                   delete front;
                   front  = next;
                  }
                  }
                  //-------------------------------------------------------------------------
                  void Queue::add(MatrixNode Matrix){  //入队
                        Node *p = new Node;
                    p->data = Matrix;
                    p->link = NULL;
                   
                    if(front == NULL){
                    front = p;
                    rear = p;
                    }
                    else{
                     
                    rear->link = p;
                    rear = p;
                    }
                    num = num + 1;
                  }
                  //------------------------------------------------------------------------
                  MatrixNode Queue::putout(){                //出队
                  MatrixNode mat;
                  Node *next;
                  if(num == 0) {           ////若队空则报错
                     cout<<"无法出队"<<endl;


                  9楼2009-11-26 20:31
                  回复
                    exit(1);
                    }  
                    mat = front->data;
                    next = front->link;
                    delete front;
                    front = next;
                    num = num -1;
                    return mat;
                     }
                    //-------------------------------------------------------------------------
                    bool Queue::lookover(MatrixNode Matrix){         //查看是否有相同项
                         Node *next;
                         next = front;
                     while(next != NULL){
                        // mat_jug(MatrixNode M_Matrix1,MatrixNode M_Matrix2)
                     if(Matrix.mat_jug(Matrix,next->data) == true){
                     return true;
                     }
                     next = next->link;
                     }
                         return false;
                    }
                    //==========================================================================
                    //==========================================================================
                    void main(){
                     MatrixNode mat1;
                     int h0;//储存线性耗散值
                     MatrixNode mat_trn;
                     Queue Q1;//未拓展但需拓展的矩阵类
                      Queue Q2;//拓展过的节点
                      Queue Q3;//储存路径
                      Node *next1;
                      Node *next2;
                      
                      mat1 = mat1.fuzhi(mat1);
                      h0 = mat1.h;
                      Q1.add(mat1);
                      next1 = Q1.front;
                      Q2.add(mat1);
                      Q3.add(mat1);
                     while(Q1.num != 0){
                     //-------向上移   
                     mat_trn = Q1.front->data;


                    10楼2009-11-26 20:31
                    回复
                      mat_trn = mat_trn.up_move(mat_trn);
                       
                       if(mat_trn.PlaceAndZero(mat_trn) == false){
                       if(Q2.lookover(mat_trn) == false){
                              Q2.add(mat_trn);
                       }
                       }
                       if(mat_trn.PlaceAndZero(mat_trn) == false){
                          if(mat_trn.h <= h0){
                              if(Q1.lookover(mat_trn) == false){
                      if(mat_trn.h < h0){                      //如果单调递减则是路径,保存倒队列3
                            Q3.add(mat_trn);

                      h0 = mat_trn.h;                          //赋予新的耗散值
                          Q1.add(mat_trn);
                              if(Q1.rear->data.m == 8) break;          //若全在位则跳出循环
                      }
                      }
                       }
                        
                        //--------向下移
                           mat_trn = Q1.front->data;
                           mat_trn = mat_trn.down_move(mat_trn);
                       
                       if(mat_trn.PlaceAndZero(mat_trn) == false){
                            if(Q2.lookover(mat_trn) == false){
                            Q2.add(mat_trn);
                                }  
                      }
                       if(mat_trn.PlaceAndZero(mat_trn) == false){
                           if(mat_trn.h <= h0){
                               if(Q1.lookover(mat_trn) == false){
                              if(mat_trn.h < h0){
                          Q3.add(mat_trn);
                      }
                      h0 = mat_trn.h;
                      Q1.add(mat_trn);
                              if(Q1.rear->data.m == 8) break;
                       }
                       }
                       }
                         //--------向左移


                      11楼2009-11-26 20:32
                      回复
                        mat_trn = Q1.front->data;
                             mat_trn = mat_trn.left_move(mat_trn);
                         
                         if(mat_trn.PlaceAndZero(mat_trn) == false){
                             if(Q2.lookover(mat_trn) == false){ 
                               Q2.add(mat_trn);
                         }
                         }
                         if(mat_trn.PlaceAndZero(mat_trn) == false){     
                              if(mat_trn.h <= h0){
                                   if(Q1.lookover(mat_trn) == false){
                           if(mat_trn.h < h0){
                              Q3.add(mat_trn);
                           }
                           h0 = mat_trn.h; 
                           Q1.add(mat_trn);
                           if(Q1.rear->data.m == 8) break;
                           } 
                          } 
                         }
                         //--------向右移
                             mat_trn = Q1.front->data;
                             mat_trn = mat_trn.right_move(mat_trn);
                         if(mat_trn.PlaceAndZero(mat_trn) == false){
                             if(Q2.lookover(mat_trn) == false){
                             Q2.add(mat_trn);
                         }
                         }
                         if(mat_trn.PlaceAndZero(mat_trn) == false){
                                if(mat_trn.h <= h0){
                                     if(Q1.lookover(mat_trn) == false){
                                     if(mat_trn.h < h0){
                                 Q3.add(mat_trn);
                         } 
                             h0 = mat_trn.h;  
                         Q1.add(mat_trn);
                                     if(Q1.rear->data.m == 8) break;
                         }
                        }
                         }
                         mat_trn = Q1.putout();
                          
                         }


                        12楼2009-11-26 20:34
                        回复
                          if(Q1.num = 0){ 
                             cout<<"无法找到路径"<<endl;
                             }
                            
                             else{
                                 next2 = Q2.front;
                             cout<<"拓展过的结点为:"<<endl;
                             while(next2 != NULL){
                                 next2->data.printMatrix(next2->data.place);
                             next2 = next2->link;
                             }
                            cout<<"路径为:"<<endl;
                             next2 = Q3.front;
                             while(next2 != NULL){
                                 next2->data.printMatrix(next2->data.place);
                             next2 = next2->link;
                             }
                             }
                          }


                          13楼2009-11-26 20:35
                          回复