算法老师给了一份关于九宫拼图的算法过程用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 }