• Android实现九宫拼图过程记录


      算法老师给了一份关于九宫拼图的算法过程用C++写的,让我们自己封装,成为一个有图形界面的工程,我接触过android,c++的mfc,Java的图形界面JUI,网页的css、html、javascript,Unity3D;但感觉最熟悉的还是利用android来写比较熟悉,可能是各种组件之间的操作不久前才完成了一个app的原因吧,所以我选择安卓。老师给了两周的时间,全凭自愿吧。我觉得我可以尝试一下。

      首先需要吧老师给的C++算法代码转换成Java代码,老师给的代码如下:

      1 /*****************************/
      2 /*  EIGHT   DIGIT   PROBLEM  */
      3 /*  唐国峰  2012年4月23日  */
      4 /*****************************/ 
      5  
      6 // 预编译命令
      7 #include "iostream"
      8 #include "stdlib.h"
      9 using namespace std;
     10  
     11 //棋盘大小
     12 #define size 3
     13  
     14 //定义二维数组来存储数据表示某一个特定状态
     15 typedef int status[size][size];
     16  
     17 //定义状态图中的节点数据结构,即节点的状态信息等
     18 typedef struct Node
     19 {
     20     status data;                    //节点所存储的状态
     21     struct Node *parent;            //指向节点的父亲节点
     22     struct SpringLink *child;        //指向节点的后继节点
     23     struct Node *next;            //指向链表的后一个节点
     24     int f_value;                    //由初始状态经由当前节点至目标状态的总耗散值
     25     int g_value;                    //由初始状态经到当前节点实际耗散值
     26     int h_value;                    //由当前节点到目标状态的预计耗散值
     27 }NNode, *PNode;
     28  
     29  
     30 //定义表述指向当前节点的扩展节点的链表
     31 typedef struct SpringLink
     32 {
     33     struct Node *pointData;            //指向节点的指针
     34     struct SpringLink *next;        //指向当前节点的其他扩展节点
     35 }SPLink, *PSPLink;
     36  
     37 //声明OPEN表和CLOSED表
     38 PNode open;
     39 PNode closed;
     40  
     41 //计算棋盘状态的逆序数
     42 int InverseNumber(status a)
     43 {
     44     int i, j, sum=0;
     45     int data_chang[size*size]={0};
     46  
     47     //将二维数组转换成一维数组,以方便求逆序数
     48     for(i=0;i<size;i++)
     49     {
     50         for(j=0;j<size;j++)
     51         {
     52             data_chang[i*size+j]=a[i][j];        
     53         }
     54     }
     55  
     56  
     57     //计算序列中除零外的逆序数
     58     for(i=0;i<=size*size;i++) 
     59     {
     60         if(data_chang[i]!=0)
     61         {
     62             //要比较多少次,从最后一个元素开始比较
     63             for(j=i;j>=0;j--)        
     64             {   
     65                 //当后一个数比前一个数小时
     66                 if(data_chang[i]<data_chang[j])   
     67                 {
     68                     sum++;
     69                 }
     70             } 
     71         }
     72     }
     73     return sum;
     74 }
     75  
     76 //判断是否存在解决方案
     77 bool hasSolution(status startStatus,status targetStatus)
     78 {
     79     int startInverseNumber=InverseNumber(startStatus);
     80     int tatgetInverseNumber=InverseNumber(targetStatus);
     81  
     82     //判断初始状态和目标状态除零外的序列逆序数奇偶性,相同则可求值,不同则不可求
     83     if( (startInverseNumber%2) != (tatgetInverseNumber%2) )
     84     {
     85         return false;
     86     }
     87     else
     88     {
     89         return true;
     90     }
     91 }
     92  
     93  
     94 //初始化一个空链表
     95 void initLink(PNode &Head)
     96 {
     97     Head = (PNode)malloc(sizeof(NNode));
     98     Head->next = NULL;
     99 }
    100  
    101  
    102 //判断链表是否为空
    103 bool isEmpty(PNode Head)
    104 {
    105     if(Head->next == NULL)
    106     {
    107         return true;
    108     }
    109     else
    110     {
    111         return false;
    112     }
    113 }
    114  
    115  
    116 //从链表中拿出一个数据
    117 void popNode(PNode &Head , PNode &FNode)
    118 {
    119     if(isEmpty(Head))
    120     {
    121         FNode = NULL;
    122         return;
    123     }
    124     FNode = Head->next;
    125     Head->next = Head->next->next;
    126     FNode->next = NULL;
    127 }
    128  
    129 //向节点的最终后继节点链表中添加新的子节点
    130 void addSpringNode(PNode &Head , PNode newData)
    131 {
    132     PSPLink newNode = (PSPLink)malloc(sizeof(SPLink));
    133     newNode->pointData = newData;
    134  
    135     newNode->next = Head->child;
    136     Head->child = newNode;
    137 }
    138  
    139 //释放状态图中存放节点后继节点地址的空间
    140 void freeSpringLink(PSPLink &Head)
    141 {
    142     PSPLink tmm;
    143  
    144     while(Head != NULL)
    145     {
    146         tmm = Head;
    147         Head = Head->next;
    148         free(tmm);
    149     }
    150 }
    151  
    152 //释放open表与closed表中的资源
    153 void freeLink(PNode &Head)
    154 {
    155     PNode tmn;
    156  
    157     tmn = Head;
    158     Head = Head->next;
    159     free(tmn);
    160  
    161     while(Head != NULL)
    162     {
    163         //首先释放存放节点后继节点地址的空间
    164         freeSpringLink(Head->child);
    165         tmn = Head;
    166         Head = Head->next;
    167         free(tmn);
    168     }
    169 }
    170  
    171 //向普通链表中添加一个节点
    172 void addNode(PNode &Head , PNode &newNode)
    173 {
    174     newNode->next = Head->next;
    175     Head->next = newNode;
    176 }
    177  
    178 //向非递减排列的链表中添加一个节点
    179 void addAscNode(PNode &Head , PNode &newNode)
    180 {
    181     PNode P;
    182     PNode Q;
    183  
    184     P = Head->next;
    185     Q = Head;
    186     while(P != NULL && P->f_value < newNode->f_value)
    187     {
    188         Q = P;
    189         P = P->next;
    190     }
    191     //上面判断好位置之后,下面就是简单的插入节点了
    192     newNode->next = Q->next;
    193     Q->next = newNode;
    194 }
    195  
    196 //计算节点到目标状态的预计耗散值
    197 int computeh_value(PNode theNode,status targetStatus)
    198 {
    199     int num = 0;
    200     for(int i = 0 ; i < 3 ; i++)
    201     {
    202         for(int j = 0 ; j < 3 ; j++)
    203         {
    204             if(theNode->data[i][j] != targetStatus[i][j])
    205             {
    206                 num++;
    207             }
    208         }
    209     }
    210     return num;
    211 }
    212  
    213 //计算节点的f,g,h值
    214 void computeAllValue(PNode &theNode , PNode parentNode, status targetStatus)
    215 {
    216     if(parentNode == NULL)
    217     {
    218         theNode->g_value = 0;
    219     }
    220     else
    221     {
    222         theNode->g_value = parentNode->g_value + 1;
    223     }
    224  
    225     theNode->h_value = computeh_value(theNode,targetStatus);
    226     theNode->f_value = theNode->g_value + theNode->h_value;
    227 }
    228  
    229 //初始化函数,进行算法初始条件的设置
    230 void initial(status startStatus,status targetStatus)
    231 {
    232     //初始化open以及closed表
    233     initLink(open);
    234     initLink(closed);
    235  
    236     //初始化起始节点,令初始节点的父节点为空节点
    237     PNode NULLNode = NULL;
    238     PNode StartNode = (PNode)malloc(sizeof(NNode));
    239     for(int i = 0 ; i < 3 ; i++)
    240     {
    241         for(int j = 0 ; j < 3 ; j++)
    242         {
    243             StartNode->data[i][j] = startStatus[i][j];
    244         }
    245     }
    246     StartNode->parent = NULL;
    247     StartNode->child = NULL;
    248     StartNode->next = NULL;
    249     computeAllValue(StartNode, NULLNode,targetStatus);
    250  
    251     //起始节点进入OPEN表
    252     addAscNode(open , StartNode);
    253 }
    254  
    255 //将B节点的状态赋值给A节点
    256 void statusAEB(PNode &ANode , PNode BNode)
    257 {
    258     for(int i = 0 ; i < 3 ; i++)
    259     {
    260         for(int j = 0 ; j < 3 ; j++)
    261         {
    262             ANode->data[i][j] = BNode->data[i][j];
    263         }
    264     }
    265 }
    266  
    267  
    268 //两个节点是否有相同的状态
    269 bool hasSameStatus(PNode ANode , PNode BNode)
    270 {
    271     for(int i = 0 ; i < size ; i++)
    272     {
    273         for(int j = 0 ; j < size ; j++)
    274         {
    275             if(ANode->data[i][j] != BNode->data[i][j])
    276                 return false;
    277         }
    278     }
    279     return true;
    280 }
    281  
    282 //节点与其祖先节点是否有相同的状态
    283 bool hasAnceSameStatus(PNode OrigiNode , PNode AnceNode)
    284 {
    285     while(AnceNode != NULL)
    286     {
    287         if(hasSameStatus(OrigiNode , AnceNode))
    288             return true;
    289         AnceNode = AnceNode->parent;
    290     }
    291     return false;
    292 }
    293  
    294 //取得方格中空的格子的位置
    295 void getPosition(PNode theNode , int &row , int &col)
    296 {
    297     for(int i = 0 ; i < size ; i++)
    298     {
    299         for(int j = 0 ; j < size ; j++)
    300         {
    301             if(theNode->data[i][j] == 0)
    302             {
    303                 row = i;
    304                 col = j;
    305                 return;
    306             }
    307         }
    308     }
    309 }
    310  
    311 //交换两个数字的值
    312 void changeAB(int &a , int &b)
    313 {
    314     int c;
    315     c = b;
    316     b = a;
    317     a = c;
    318 }
    319  
    320 //检查相应的状态是否在某一个链表中
    321 bool inLink(PNode spciNode , PNode theLink , PNode &theNodeLink , PNode &preNode)
    322 {
    323     preNode = theLink;
    324     theLink = theLink->next;
    325  
    326     while(theLink != NULL)
    327     {
    328         if(hasSameStatus(spciNode , theLink))
    329         {
    330             theNodeLink = theLink;
    331             return true;
    332         }
    333         preNode = theLink;
    334         theLink = theLink->next;
    335     }
    336     return false;
    337 }
    338  
    339 //产生节点的后继节点链表
    340 void SpringLink(PNode theNode , PNode &spring, status targetStatus)
    341 {
    342     int row;
    343     int col;
    344  
    345     getPosition(theNode , row , col);
    346  
    347     //空的格子右边的格子向左移动
    348     if(col != 2)
    349     {
    350         PNode rlNewNode = (PNode)malloc(sizeof(NNode));
    351         statusAEB(rlNewNode, theNode);
    352         changeAB(rlNewNode->data[row][col], rlNewNode->data[row][col + 1]);
    353         if(hasAnceSameStatus(rlNewNode, theNode->parent))
    354         {
    355             free(rlNewNode);//与父辈相同,丢弃本节点
    356         }
    357         else
    358         {
    359             rlNewNode->parent = theNode;
    360             rlNewNode->child = NULL;
    361             rlNewNode->next = NULL;
    362             computeAllValue(rlNewNode, theNode, targetStatus);
    363             //将本节点加入后继节点链表
    364             addNode(spring, rlNewNode);
    365         }
    366     }
    367     //空的格子左边的格子向右移动
    368     if(col != 0)
    369     {
    370         PNode lrNewNode = (PNode)malloc(sizeof(NNode));
    371         statusAEB(lrNewNode, theNode);
    372         changeAB(lrNewNode->data[row][col], lrNewNode->data[row][col - 1]);
    373         if(hasAnceSameStatus(lrNewNode, theNode->parent))
    374         {
    375             free(lrNewNode);//与父辈相同,丢弃本节点
    376         }
    377         else
    378         {
    379             lrNewNode->parent = theNode;
    380             lrNewNode->child = NULL;
    381             lrNewNode->next = NULL;
    382             computeAllValue(lrNewNode, theNode, targetStatus);
    383             //将本节点加入后继节点链表
    384             addNode(spring , lrNewNode);
    385         }
    386     }
    387     //空的格子上边的格子向下移动
    388     if(row != 0)
    389     {
    390         PNode udNewNode = (PNode)malloc(sizeof(NNode));
    391         statusAEB(udNewNode , theNode);
    392         changeAB(udNewNode->data[row][col], udNewNode->data[row - 1][col]);
    393         if(hasAnceSameStatus(udNewNode, theNode->parent))
    394         {
    395             free(udNewNode);//与父辈相同,丢弃本节点
    396         }
    397         else
    398         {
    399             udNewNode->parent = theNode;
    400             udNewNode->child = NULL;
    401             udNewNode->next = NULL;
    402             computeAllValue(udNewNode, theNode, targetStatus);
    403             //将本节点加入后继节点链表
    404             addNode(spring, udNewNode);
    405         }
    406     }
    407     //空的格子下边的格子向上移动
    408     if(row != 2)
    409     {
    410         PNode duNewNode = (PNode)malloc(sizeof(NNode));
    411         statusAEB(duNewNode, theNode);
    412         changeAB(duNewNode->data[row][col], duNewNode->data[row + 1][col]);
    413         if(hasAnceSameStatus(duNewNode, theNode->parent))
    414         {
    415             free(duNewNode);//与父辈相同,丢弃本节点
    416         }
    417         else
    418         {
    419             duNewNode->parent = theNode;
    420             duNewNode->child = NULL;
    421             duNewNode->next = NULL;
    422             computeAllValue(duNewNode, theNode, targetStatus);
    423             //将本节点加入后继节点链表
    424             addNode(spring , duNewNode);
    425         }
    426     }
    427 }
    428  
    429 //输出给定节点的状态
    430 void outputStatus(PNode stat)
    431 {
    432     for(int i = 0 ; i < 3 ; i++)
    433     {
    434         for(int j = 0 ; j < 3 ; j++)
    435         {
    436             cout << stat->data[i][j] << " ";
    437         }
    438         cout << endl;
    439     }
    440 }
    441  
    442 //输出最佳的路径
    443 void outputBestRoad(PNode goal)
    444 {
    445     int deepnum = goal->g_value;
    446  
    447     if(goal->parent != NULL)
    448     {
    449         outputBestRoad(goal->parent);
    450     }
    451     cout << "" << deepnum-- << "步的状态:" << endl;
    452     outputStatus(goal);
    453 }
    454  
    455  
    456 void AStar(status startStatus,status targetStatus)
    457 {
    458     PNode tmpNode;                        //指向从open表中拿出并放到closed表中的节点的指针
    459     PNode spring;                        //tmpNode的后继节点链
    460     PNode tmpLNode;                        //tmpNode的某一个后继节点
    461     PNode tmpChartNode;
    462     PNode thePreNode;                    //指向将要从closed表中移到open表中的节点的前一个节点的指针
    463     bool getGoal = false;                //标识是否达到目标状态
    464     long numcount = 1;                    //记录从open表中拿出节点的序号
    465  
    466     initial(startStatus,targetStatus);    //对函数进行初始化
    467     initLink(spring);                    //对后继链表的初始化
    468     tmpChartNode = NULL;
    469  
    470     cout << "从OPEN表中拿出的节点的状态及相应的值" << endl;
    471     while(!isEmpty(open))
    472     {
    473         //从OPEN表中拿出f值最小的元素,并将拿出的元素放入CLOSED表中
    474         popNode(open, tmpNode);
    475         addNode(closed, tmpNode);
    476  
    477  
    478         cout << "" << numcount++ << "个状态是:" << endl;
    479         outputStatus(tmpNode);
    480         cout << "其f值为:" << tmpNode->f_value << endl;
    481         cout << "其g值为:" << tmpNode->g_value << endl;
    482         cout << "其h值为:" << tmpNode->h_value << endl;
    483  
    484  
    485         //如果拿出的元素是目标状态则跳出循环
    486         if(computeh_value(tmpNode, targetStatus) == 0)
    487         {
    488             getGoal = true;
    489             break;
    490         }
    491  
    492         //产生当前检测节点的后继(与祖先不同)节点列表,产生的后继节点的parent属性指向当前检测的节点
    493         SpringLink(tmpNode, spring, targetStatus);
    494  
    495         //遍历检测节点的后继节点链表
    496         while(!isEmpty(spring))
    497         {
    498             popNode(spring , tmpLNode);
    499             //状态在OPEN表中已经存在,thePreNode参数在这里并不起作用
    500             if(inLink(tmpLNode , open , tmpChartNode , thePreNode))
    501             {
    502                 addSpringNode(tmpNode , tmpChartNode);
    503                 if(tmpLNode->g_value < tmpChartNode->g_value)
    504                 {
    505                     tmpChartNode->parent = tmpLNode->parent;
    506                     tmpChartNode->g_value = tmpLNode->g_value;
    507                     tmpChartNode->f_value = tmpLNode->f_value;
    508                 }
    509                 free(tmpLNode);
    510             }
    511             //状态在CLOSED表中已经存在
    512             else if(inLink(tmpLNode, closed, tmpChartNode, thePreNode))
    513             {
    514                 addSpringNode(tmpNode, tmpChartNode);
    515                 if(tmpLNode->g_value < tmpChartNode->g_value)
    516                 {
    517                     PNode commu;
    518                     tmpChartNode->parent = tmpLNode->parent;
    519                     tmpChartNode->g_value = tmpLNode->g_value;
    520                     tmpChartNode->f_value = tmpLNode->f_value;
    521                     freeSpringLink(tmpChartNode->child);
    522                     tmpChartNode->child = NULL;
    523                     popNode(thePreNode, commu);
    524                     addAscNode(open, commu);
    525                 }
    526                 free(tmpLNode);
    527             }
    528             //新的状态即此状态既不在OPEN表中也不在CLOSED表中
    529             else
    530             {
    531                 addSpringNode(tmpNode, tmpLNode);
    532                 addAscNode(open, tmpLNode);
    533             }
    534         }
    535     }
    536  
    537     //目标可达的话,输出最佳的路径
    538     if(getGoal)
    539     {
    540         cout << endl;
    541         cout << "路径长度为:" << tmpNode->g_value << endl;
    542         outputBestRoad(tmpNode);
    543     }
    544  
    545     //释放节点所占的内存
    546     freeLink(open);
    547     freeLink(closed);
    548 }
    549  
    550 int main()
    551 {
    552  
    553     //开始状态和目标状态
    554     status startStatus = { 6, 3, 0, 2, 4, 8, 1, 5, 7};//2, 8, 3, 1, 6, 4, 7, 0, 5};
    555     status targetStatus = {1, 2, 3, 4, 5, 6, 7, 8, 0};
    556  
    557     if(hasSolution(startStatus,targetStatus))
    558     {
    559         AStar(startStatus,targetStatus);
    560     }
    561     else
    562     {
    563         cout << "从当前输入的初始状态无法经过有限步数变换至您期望的目标状态!" << endl;
    564     }
    565     system("pause");
    566 }
    View Code
  • 相关阅读:
    Falsy Bouncer(算法)
    Check for Palindromes(算法)
    ecshop 修改模板可输出php代码
    ecshop显示所有分类树栏目
    ecshop首页调用评论及图片
    ECSHOP 商品评论条件修改——购买过该商品且只能评价一次(购买多少次能评价多少次)
    PS4破解
    Spring BeanFactory与FactoryBean的区别及其各自的详细介绍于用法
    Java中类方法与实例方法的区别
    Java中类及方法的加载顺序
  • 原文地址:https://www.cnblogs.com/awayfly/p/7750591.html
Copyright © 2020-2023  润新知