zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    sqlhelper使用指南
    大三学长带我学习JAVA。作业1. 第1讲.Java.SE入门、JDK的下载与安装、第一个Java程序、Java程序的编译与执行 大三学长带我学习JAVA。作业1.
    pku1201 Intervals
    hdu 1364 king
    pku 3268 Silver Cow Party
    pku 3169 Layout
    hdu 2680 Choose the best route
    hdu 2983
    pku 1716 Integer Intervals
    pku 2387 Til the Cows Come Home
  • 原文地址:https://www.cnblogs.com/awayfly/p/7750591.html
Copyright © 2011-2022 走看看