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)
 49     {
 50         for(j=0;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

 

你可能感兴趣的:(Android实现九宫拼图过程记录)