2014-09-21 52 views
0

我想編碼一個算法,以便它可以從網格的任何「開始」單元格開始(例如,單元格號4圖片),並通過網格的每個單元格解析一次。網格可以是任何尺寸的3x3,4x4,8x8等。查找從單元格x到單元格y的網格路徑,以便所有單元格都被解析一次

以下代碼可生成此類路徑。對於8x8網格中的許多單元格都可以正常工作。但對於許多細胞來說,搜尋一條路徑需要很長的時間。

我想知道是否有一些可以引用的更好的解決方案,以便可以優化解決方案。

package 
{ 

import flash.display.MovieClip; 

public class Main extends MovieClip 
{ 
    private var rand_Num; 


    public var node0_Mc:MovieClip ,node1_Mc:MovieClip,node2_Mc:MovieClip,node3_Mc:MovieClip,node4_Mc:MovieClip,node5_Mc:MovieClip,node6_Mc:MovieClip,node7_Mc:MovieClip,node8_Mc:MovieClip,node9_Mc:MovieClip, 
    node10_Mc:MovieClip,node11_Mc:MovieClip,node12_Mc:MovieClip,node13_Mc:MovieClip,node14_Mc:MovieClip,node15_Mc:MovieClip,node16_Mc:MovieClip,node17_Mc:MovieClip,node18_Mc:MovieClip,node19_Mc:MovieClip, 
    node20_Mc:MovieClip,node21_Mc:MovieClip,node22_Mc:MovieClip,node23_Mc:MovieClip,node24_Mc:MovieClip,node25_Mc:MovieClip,node26_Mc:MovieClip,node27_Mc:MovieClip,node28_Mc:MovieClip,node29_Mc:MovieClip, 
    node30_Mc:MovieClip,node31_Mc:MovieClip,node32_Mc:MovieClip,node33_Mc:MovieClip,node34_Mc:MovieClip,node35_Mc:MovieClip,node36_Mc:MovieClip,node37_Mc:MovieClip,node38_Mc:MovieClip,node39_Mc:MovieClip, 
    node40_Mc:MovieClip,node41_Mc:MovieClip,node42_Mc:MovieClip,node43_Mc:MovieClip,node44_Mc:MovieClip,node45_Mc:MovieClip,node46_Mc:MovieClip,node47_Mc:MovieClip,node48_Mc:MovieClip,node49_Mc:MovieClip, 
    node50_Mc:MovieClip,node51_Mc:MovieClip,node52_Mc:MovieClip,node53_Mc:MovieClip,node54_Mc:MovieClip,node55_Mc:MovieClip,node56_Mc:MovieClip,node57_Mc:MovieClip,node58_Mc:MovieClip,node59_Mc:MovieClip, 
    node60_Mc:MovieClip, node61_Mc:MovieClip, node62_Mc:MovieClip, node63_Mc:MovieClip; 
    public const NUM_COLS:Number = 8; 
    // 3 ;// 4 ; 
    public const NUM_ROWS:Number = 8;// 3 ;// 4 ; 



    var chain_Arr:Array = []; 
    var blockIndex_Arr:Array = []; 
    var nodearr:Array; 

    var adjacentNodeArray_Arr:Array = []; 
    var parsedNodeIndex_Arr:Array = []; 
    var validNextAdjacentNodeIndexArray_Arr:Array = []; 
    var validPreviousAdjacentNodeIndexArray_Arr:Array = []; 
    var savePair_Arr:Array = []; 
    var countChain_Num:Number = 0; 
    var saveParent_Arr:Array = []; 

    public function Main() 
    { 
     // constructor code 
     nodearr = [node0_Mc,node1_Mc,node2_Mc,node3_Mc,node4_Mc,node5_Mc,node6_Mc,node7_Mc,node8_Mc,node9_Mc,node10_Mc,node11_Mc,node12_Mc,node13_Mc,node14_Mc,node15_Mc,node16_Mc,node17_Mc,node18_Mc,node19_Mc,node20_Mc,node21_Mc,node22_Mc,node23_Mc,node24_Mc,node25_Mc,node26_Mc,node27_Mc,node28_Mc,node29_Mc,node30_Mc,node31_Mc,node32_Mc,node33_Mc,node34_Mc,node35_Mc,node36_Mc,node37_Mc,node38_Mc,node39_Mc,node40_Mc,node41_Mc,node42_Mc,node43_Mc,node44_Mc,node45_Mc,node46_Mc,node47_Mc,node48_Mc,node49_Mc,node50_Mc,node51_Mc,node52_Mc,node53_Mc,node54_Mc,node55_Mc,node56_Mc,node57_Mc,node58_Mc,node59_Mc,node60_Mc,node61_Mc,node62_Mc,node63_Mc]; 

     var possibleAdjacentNodeIndex_Arr:Array = []; 

     initValidNextAdjacentNodeIndexArray(); 
     initValidPreviousAdjacentNodeIndexArray(); 

     savePair_Arr = []; 

     var startIndex_num:Number = 45;// 0 ; 

     rand_Num = 62;// randomRange(10, (NUM_COLS * NUM_ROWS) - 1); 
     getAllChainsFromParamNodeIndexParamParentChain(startIndex_num,[startIndex_num]); 


    } 

    function initValidNextAdjacentNodeIndexArray():void 
    { 
     for (var index_num = 0; index_num < NUM_COLS*NUM_ROWS; index_num++) 
     { 
      validNextAdjacentNodeIndexArray_Arr[index_num] = getValidNodeIndexArrayAdjacentToParamNodeIndex(index_num); 
      //trace(validNextAdjacentNodeIndexArray_Arr[index_num]); 
     } 
    } 

    function initValidPreviousAdjacentNodeIndexArray():void 
    { 
     for (var index_num = 0; index_num < NUM_COLS*NUM_ROWS; index_num++) 
     { 
      validPreviousAdjacentNodeIndexArray_Arr[index_num] = getValidNodeIndexArrayAdjacentToParamNodeIndex(index_num); 
      //trace(validNextAdjacentNodeIndexArray_Arr[index_num]); 
     } 
    } 

    //function getAllChainsFromParamNodeIndexParamParentChain( path_arr:Array,index_param_num:Number):void 

    function getAllChainsFromParamNodeIndexParamParentChain( index_param_num:Number, parent_arr:Array):void 
    { 
     var i; 

     if (countChain_Num > 15) 
     { 
      return; 
     } 


     reinitPath(); 

     var adjacent_arr = getValidNodeIndexArrayAdjacentToParamNodeIndex(index_param_num); 

     for (i = 0; i < adjacent_arr.length; i++) 
     { 



      reinitPath(); 
      if ((checkRepeat(chain_Arr))) 
      { 

       continue; 
      } 


      chain_Arr.push(adjacent_arr[i]); 
      //trace("chain starts from", chain_Arr); 


      var nodeIndex_num:Number = adjacent_arr[i]; 
      var nodeIndexExist_num = 0; 
      var parentNode_num:Number = parent_arr[parent_arr.length - 1]; 

      var bool:Boolean; 
      while (isNaN(nodeIndex_num) == false) 
      { 

       //var childNodeIndex_num = manageValidAdjacentIndexArray(parent_arr[parent_arr.length-1], parentNode_num , nodeIndex_num); 
       var childNodeIndex_num = manageValidAdjacentIndexArray(adjacent_arr[i],parentNode_num,nodeIndex_num); 
       //var childNodeIndex_num = manageValidAdjacentIndexArray(parentNode_num, parentNode_num , nodeIndex_num); 
       parentNode_num = nodeIndex_num; 
       nodeIndex_num = childNodeIndex_num; 

       if ((checkRepeat(chain_Arr))) 
       { 

        break; 
       } 


       if (isNaN(nodeIndex_num) == false) 
       { 
        chain_Arr.push(nodeIndex_num); 
       } 


      } 


      if (chain_Arr.length > NUM_COLS * NUM_ROWS - 1) 
      { 


       //if (!(checkRepeat(chain_Arr))) 
       { 
        trace(chain_Arr); 
        saveParent_Arr[saveParent_Arr.length ] = new Array(); 
        for (var k = 0; k < rand_Num; k++) 
        { 
         saveParent_Arr[saveParent_Arr.length - 1].push( chain_Arr[k]); 
        } 

        countChain_Num++; 
       } 



      } 


     }; 




     for (i = 0; i < adjacent_arr.length; i++) 
     { 




      var arr2:Array = parent_arr.slice(); 

      arr2.push(adjacent_arr[i]); 

      getAllChainsFromParamNodeIndexParamParentChain( adjacent_arr[i], arr2); 
     } 

     function reinitPath():void 
     { 
      chain_Arr = []; 

      chain_Arr = chain_Arr.concat(parent_arr); 
     } 


    } 

    private function checkRepeat(chain_arr:Array):Boolean 
    { 
     var bool:Boolean; 
     var num = rand_Num; 
     if (chain_arr.length >= num - 1) 
     { 


      for (var i = 0; i < saveParent_Arr.length; i++) 
      { 
       //trace(saveParent_Arr[i][0], saveParent_Arr[i][1]); 
       if (saveParent_Arr[i] != undefined) 
       { 
        var z = 0; 
        for (var j = 0; j < num; j++) 
        { 
         if (saveParent_Arr[i][j] == chain_arr[j]) 
         { 
          z++; 
          if (z >= num) 
          { 
           bool = true; 
           break; 
          } 
         } 
         else 
         { 
          break; 
         } 
        } 

        if (bool) 
        { 
         break; 
        } 

       } 

      } 

     } 



     return bool; 


    } 
    function randomRange(minNum:Number, maxNum:Number):Number 
    { 
     return (Math.floor(Math.random() * (maxNum - minNum + 1)) + minNum); 
    } 

    function randomizeArray(arr:Array):void 
    { 
     for (var i = 0; i < arr.length; i++) 
     { 
      var random = randomRange(0,arr.length - 1); 
      var temp = arr[i]; 
      arr[i] = arr[random]; 
      arr[random] = temp; 
     } 

    } 


    //will send NaN if no valid adjacent index array is possible 
    private function manageValidAdjacentIndexArray(chainStartIndex_num:Number, parentNodeIndex_param_num:Number, nodeIndex_num:Number):Number 
    { 
     var num_nan:Number; 
     var ret_num:Number; 
     var j; 
     //var tot:Number = validNextAdjacentNodeIndexArray_Arr[nodeIndex_num].length ; 

     j = 0; 
     var arr:Array = validNextAdjacentNodeIndexArray_Arr[nodeIndex_num];// getValidNodeIndexArrayAdjacentToParamNodeIndex(nodeIndex_num) ; 

     randomizeArray(arr); 

     while (arr.length > 0)// && isNaN(ret_num)) 
     { 

      ret_num = arr[j];//validNextAdjacentNodeIndexArray_Arr[nodeIndex_num][j] ; 

      //if this index is present in chain then remove it off 
      if (chain_Arr.indexOf(ret_num) >= 0) 
      { 
       //j++ ; 
       ret_num = num_nan; 
      } 


      j++; 

      if (j >= arr.length) 
      { 
       ret_num = num_nan; 
       break; 
      } 


     } 


     return ret_num; 
    } 



    private function getValidAdjacentIndexToParamNodeIndex(nodeIndex_param_num:Number):Number 
    { 
     var adjacentNode_arr:Array = []; 
     var adjacentRow_arr:Array = []; 
     var adjacentCol_arr:Array = []; 

     var allIndex_arr:Array = []; 

     var r:Number; 
     var c:Number; 

     var row_num:Number = int(nodeIndex_param_num/NUM_COLS); 
     var col_num:Number = (nodeIndex_param_num % NUM_COLS); 

     allIndex_arr = getAllAdjacentNodeIndexArray(row_num,col_num); 

     validateIndices(allIndex_arr); 

     var ret_num:Number; 
     ret_num = allIndex_arr[0]; 
     return ret_num; 

    } 



    function getValidNodeIndexArrayAdjacentToParamNodeIndex(nodeIndex_param_num:Number):Array 
    { 
     var adjacentNode_arr = []; 

     for (var positionId_num = 0; positionId_num < 8; positionId_num++) 
     { 
      var num:Number = getNodeIndexAtParamPositionIdOfParamIndex(positionId_num,nodeIndex_param_num); 

      if (isNaN(num)) 
      { 
      } 
      else 
      { 
       adjacentNode_arr.push(num); 
      } 
     } 

     return adjacentNode_arr; 
    } 



    private function getAllAdjacentNodeIndexArray(row_num:Number, col_num:Number,within_arr:Array=null):Array 
    { 

     var num:Number; 
     var index_arr:Array = [num,num,num,num,num,num,num,num]; 
     var r:Number; 
     var c:Number; 

     if (row_num > 0) 
     { 
      r = row_num - 1; 
      c = col_num; 
      index_arr[0] = r * NUM_COLS + c; 

     } 


     if (col_num < NUM_COLS-1) 
     { 
      r = row_num; 
      c = col_num + 1; 
      index_arr[1] = r * NUM_COLS + c; 
     } 


     if (row_num < NUM_ROWS-1) 
     { 
      r = row_num + 1; 
      c = col_num; 
      index_arr[2] = r * NUM_COLS + c; 

     } 

     if (col_num > 0) 
     { 
      r = row_num; 
      c = col_num - 1; 
      index_arr[3] = r * NUM_COLS + c; 
     } 
     /////////////////////////////////////////// 


     if (row_num > 0 && col_num > 0) 
     { 
      r = row_num - 1; 
      c = col_num - 1; 
      index_arr[4] = r * NUM_COLS + c; 
     } 

     if (row_num > 0 && col_num < NUM_COLS-1) 
     { 
      r = row_num - 1; 
      c = col_num + 1; 
      index_arr[5] = r * NUM_COLS + c; 
     } 

     if (row_num < NUM_ROWS-1 && col_num < NUM_COLS-1) 
     { 
      r = row_num + 1; 
      c = col_num + 1; 
      index_arr[6] = r * NUM_COLS + c; 
     } 

     if (row_num < NUM_ROWS-1 && col_num > 0) 
     { 
      r = row_num + 1; 
      c = col_num - 1; 
      index_arr[7] = r * NUM_COLS + c; 
     } 



     return index_arr; 

    } 

    //the adjacent node must be present in within_arr, which we splice, one time for variation 
    function getNodeIndexAtParamPositionIdOfParamIndex(n:Number , nodeIndex_param_num:Number):Number 
    { 
     var adjacentNode_arr:Array = []; 
     var adjacentRow_arr:Array = []; 
     var adjacentCol_arr:Array = []; 

     var index_arr:Array = []; 

     var r:Number; 
     var c:Number; 
     var index_num:Number; 
     var row_num:Number = int(nodeIndex_param_num/NUM_COLS); 
     var col_num:Number = (nodeIndex_param_num % NUM_COLS); 

     index_arr = getAllAdjacentNodeIndexArray(row_num,col_num); 

     validateIndices(index_arr); 

     var ret_num:Number; 
     ret_num = index_arr[n]; 
     return ret_num; 

    } 

    private function validateIndices(index_arr:Array):void 
    { 
     for (var i = 0; i < index_arr.length; i++) 
     { 
      if (chain_Arr.indexOf(index_arr[i]) == -1) 
      { 
      } 
      else 
      { 
       var num:Number; 
       index_arr[i] = num;//pushing NaN 
      } 
     } 
    } 








} 

}

enter image description here

enter image description here

+0

可能重複[填充2D單個路徑的網格](http://stackoverflow.com/questions/15898884/fill-2d-grid-with-single-path) – 2014-09-21 16:25:15

回答

2

這是一個漢彌爾頓路徑問題。這是NP完整和afaik仍然沒有有效的解決方案。

檢查了這一點:hamilton paths in grid graphs(PDF)

短隨機算法解釋:Princeton Hamiltonian path problem

或維基百科:Hamiltonian path problem

編輯:

我做了一些更多的研究,併爲您的特殊情況下,強連通的正方形網格(nxn棋盤)尋找騎士之旅的warndoffs規則的變體可能會在接近線性的時間給你一個解決方案。看到這裏:A method for finding hamiltonian paths and knight tours(pdf)

+0

你是對的,這是一個網格圖,我更新了我的參考。根據我所鏈接的論文,它仍然被證明是NP完整的。 – dfherr 2014-09-21 16:25:41

+0

網格圖可以在網格中缺少邊。 – 2014-09-21 16:27:05

+1

我做了一些更多的研究,並編輯了我的答案,並提供了nxn網格(棋盤) – dfherr 2014-09-21 17:01:06

相關問題