連連看遊戲中的尋路算法( JS版 )

附件下載地址:https://download.csdn.net/download/heshiyuan1406146854/12314324

如下時關鍵 html 代碼:

<html>

<head>
  <title>xxx</title>
  <style>
    table,table tr td{
      border: 1px solid black;
    }

    tr td{
      width: 25px;
      height: 25px;
    }

    .head1{background:url(head1.jpg) no-repeat; }
    .head2{background:url(head2.jpg) no-repeat; }
    .head3{background:url(head3.jpg) no-repeat; }
    .head4{background:url(head4.jpg) no-repeat; }
    .head5{background:url(head5.jpg) no-repeat; }
    .head6{background:url(head6.jpg) no-repeat; }
    .head7{background:url(head7.jpg) no-repeat; }
    .head8{background:url(head8.jpg) no-repeat; }
    .head9{background:url(head9.jpg) no-repeat; }
    .head10{background:url(head10.jpg) no-repeat; }
    .head11{background:url(head11.jpg) no-repeat; }
    .head12{background:url(head12.jpg) no-repeat; }
    .head13{background:url(head13.jpg) no-repeat; }
    .head14{background:url(head14.jpg) no-repeat; }
    .head15{background:url(head15.jpg) no-repeat; }
    .head16{background:url(head16.jpg) no-repeat; }
    .head17{background:url(head17.jpg) no-repeat; }
    .head18{background:url(head18.jpg) no-repeat; }
    .head19{background:url(head19.jpg) no-repeat; }
    .head20{background:url(head20.jpg) no-repeat; }

    .wall{
      background-color:brown;
    }

    .road{
      background-color: green;
    }

    .empty{
      background-color: white;
    }
  </style>
</head>
<body>
  <table  cellspacing="0" cellpadding="0">
    </table>

    <button οnclick="addClearWallEvent4AllTd()" title="雙擊方塊清除障礙">清除障礙</button>
    <button οnclick="addSetWallEvent4AllTd()" title="雙擊方塊設置障礙">設置障礙</button>
    <button οnclick="clearEvent()">復位</button>
    <button οnclick="setStartPoint()">設置起點</button>
    <button οnclick="setEndPoint()">設置終點</button>
    <button οnclick="searchRoad()">開始搜索</button>
</body>
<script type="text/javascript" src="jquery-3.4.1.min.js"></script>
<script type="text/javascript">

  var row1 = -1;
  var col1 = -1;
  var row2 = -1;
  var col2 = -1;

  var rowSize = 10;
  var colSize = 10;
  var className1;
  var className2;

  var hinderClassNamePrefix =  "head";

    // 爲每個 放個添加點擊事件
    // 如果 ( row1,col1 ) 不存在 則 表示點擊的是第一個點,
    window.setTimeout( function(){
        $( "td" ).click( function(){
            // 如果點擊的有圖標的話
            var className = $( this ).attr( "class" );
            if( !className ){
                console.log( "invalid  click..." );
                return;
            }
            if( row1 == -1 || col1 == -1 ){
                row1 = parseInt( $( this ).attr( "row" ) );
                col1 = parseInt( $( this ).attr( "col" ) );
                console.log( "first click ( " + row1 + "," + col1 + " )" );
                className1 = className;
            }else if( row2 == -1 || col2 == -1 ){
                row2 = parseInt( $( this ).attr( "row" ) );
                col2 = parseInt( $( this ).attr( "col" ) );
                console.log( "second click ( " + row2 + "," + col2 + " )" );
                className2 = className;
                if( className1 == className2 ){
                    // 開始嘗試連線
                    var roadList = searchRoad2( row1,col1,row2,col2 );
                    if( roadList ){
                        console.log( "roadList.length = " + roadList.length );
                        // 消除 起始兩點
                        clearLogo( row1,col1 );
                        clearLogo( row2,col2 );
                    }else{
                        console.log("can not connection...");
                    }
                }else{
                    console.log( "兩次點擊的不是相同的圖案..." );
                }
                row1 = -1;
                col1 = -1;
                row2 = -1;
                col2 = -1;
            }
        } );
    },1000 );


  function shuffle(arr){
      var len = arr.length;
      for(var i = 0; i < len - 1; i++){
          var idx = Math.floor(Math.random() * (len - i));
          var temp = arr[idx];
          arr[idx] = arr[len - i - 1];
          arr[len - i -1] = temp;
      }
      return arr;
  }

  ( function initGame(){
      var array = [  ];
      for( var i=0;i<100;i++ ){
        array[ i ] = i%20 + 1;
      }
      array=shuffle( array );
      var index=0;
      for( var row = 0;row<10;row++ ){
          var trStr = '<tr>';
          for( var col = 0;col<10;col++ ){
              trStr+='<td class="head' + array[ index++ ] + '" row="' + row + '" col="' + col + '"></td>';
          }
          trStr+='</tr>';
          $( "table" ).append( $( trStr ) );
      }
  } )();

  function addClearWallEvent4AllTd(){
      clearEvent();
      $("td").dblclick( function(){
        $( this ).removeClass( hinderClassNamePrefix )
        $( this ).addClass( "empty" )
      } );
  }

  function addSetWallEvent4AllTd(){
      clearEvent();
      $("td").dblclick( function(){
        $( this ).removeClass( "empty" )
        $( this ).addClass( hinderClassNamePrefix )
      } );
  }

  function clearEvent(){
      $("td").unbind();
  }

  function setStartPoint(){
      clearEvent();
      $("td").dblclick( function(){
        row1 = parseInt( $( this ).attr( "row" ) );
        col1 = parseInt( $( this ).attr( "col" ) );
        console.log( "row1 = " + row1 + ",col1 = " + col1 );
      } );
  }

  function setEndPoint(){
      clearEvent();
      $("td").dblclick( function(){
        row2 = parseInt( $( this ).attr( "row" ) );
        col2 = parseInt( $( this ).attr( "col" ) );
        console.log( "row2 = " + row2 + ",col2 = " + col2 );
      } );
  }


  function searchRoad2( row1,col1,row2,col2 ){
      var maxComplexLevel = 4;
      for( var maxStraightLineCount = 1;maxStraightLineCount <= maxComplexLevel;maxStraightLineCount++ ){
          var roadList = searchRoad2maxStraightLineCount( row1,col1,row2,col2,maxStraightLineCount );
          if( roadList ){
              printRoad( roadList ); //打印路徑
              return roadList;
          }
      }
      // alert( "there is no road between [ " + row1 + "," + col1 + " ] and [ " + row2 + "," + col2 + " ]" );
      // console.log( "there is no road between [ " + row1 + "," + col1 + " ] and [ " + row2 + "," + col2 + " ]" );
      return null;
  }

  function searchRoad2maxStraightLineCount( row1,col1,row2,col2,maxStraightLineCount ){
      if( maxStraightLineCount <= 0 ){
        return null;
      }
      console.log( "maxStraightLineCount = " + maxStraightLineCount );
      if( maxStraightLineCount == 1 ){
        return search1StraightLineRoad( row1,col1,row2,col2 );
      }
      // 找到 ( row1,col1 ) 可以一條直線連接的 點 ( row1_next,col1_next ), 
      // 則問題簡化爲 找 ( row1_next,col1_next ) 和 ( row2,col2 ) 之間是否可以  maxStraightLineCount - 1 條直線連接
       // 先向左搜索
      var row1_next = row1;
      var col1_next = col1;
      while( true ){
          col1_next--;
          if( col1_next < 0 ){
              break;
          }
          var className = getClassName( row1_next,col1_next );
          // 以該前綴 開頭 
          if( className.indexOf( hinderClassNamePrefix ) == 0 ){
              break;
          }
          var roadList = searchRoad2maxStraightLineCount( row1_next,col1_next,row2,col2,maxStraightLineCount - 1 );
          if( roadList ){
            // todo  將  ( row1,col1 ) 和  ( row1_next,col1_next ) 之間的點加入 roadList
            var roadListTemp = getOneStraightLineRoadListBetween( row1,col1,row1_next,col1_next );
            for( var i in roadListTemp ){
              roadList.push( [ roadListTemp[ i ][ 0 ],roadListTemp[ i ][ 1 ] ] );
            }
            roadList.push( [ row1_next,col1_next ] );
            return roadList;
          }
      }

      // 向右搜索
      row1_next = row1;
      col1_next = col1;
      while( true ){
          col1_next++;
          if( col1_next > ( colSize - 1 ) ){
              break;
          }
          var className = getClassName( row1_next,col1_next );
          if( className.indexOf( hinderClassNamePrefix ) == 0 ){
              break;
          }
          var roadList = searchRoad2maxStraightLineCount( row1_next,col1_next,row2,col2,maxStraightLineCount - 1 );
          if( roadList ){
            // todo  將  ( row1,col1 ) 和  ( row1_next,col1_next ) 之間的點加入 roadList
            var roadListTemp = getOneStraightLineRoadListBetween( row1,col1,row1_next,col1_next );
            for( var i in roadListTemp ){
              roadList.push( [ roadListTemp[ i ][ 0 ],roadListTemp[ i ][ 1 ] ] );
            }
            roadList.push( [ row1_next,col1_next ] );
            return roadList;
          }
      }

      // 向 上搜索
      row1_next = row1;
      col1_next = col1;
      while( true ){
          row1_next--;
          if( row1_next < 0 ){
              break;
          }
          var className = getClassName( row1_next,col1_next );
          if( className.indexOf( hinderClassNamePrefix ) == 0 ){
              break;
          }
          var roadList = searchRoad2maxStraightLineCount( row1_next,col1_next,row2,col2,maxStraightLineCount - 1 );
          if( roadList ){
            // todo  將  ( row1,col1 ) 和  ( row1_next,col1_next ) 之間的點加入 roadList
            var roadListTemp = getOneStraightLineRoadListBetween( row1,col1,row1_next,col1_next );
            for( var i in roadListTemp ){
              roadList.push( [ roadListTemp[ i ][ 0 ],roadListTemp[ i ][ 1 ] ] );
            }
            roadList.push( [ row1_next,col1_next ] );
            return roadList;
          }
      }

      //向下搜索
      row1_next = row1;
      col1_next = col1;
      while( true ){
          row1_next++;
          if( row1_next > ( rowSize - 1 ) ){
              break;
          }
          var className = getClassName( row1_next,col1_next );
          if( className.indexOf( hinderClassNamePrefix ) == 0 ){
              break;
          }
          var roadList = searchRoad2maxStraightLineCount( row1_next,col1_next,row2,col2,maxStraightLineCount - 1 );
          if( roadList ){
            // todo  將  ( row1,col1 ) 和  ( row1_next,col1_next ) 之間的點加入 roadList
            var roadListTemp = getOneStraightLineRoadListBetween( row1,col1,row1_next,col1_next );
            for( var i in roadListTemp ){
              roadList.push( [ roadListTemp[ i ][ 0 ],roadListTemp[ i ][ 1 ] ] );
            }
            roadList.push( [ row1_next,col1_next ] );
            return roadList;
          }
      }
      return null;
  }

  function searchRoad(){
    searchRoad2( row1,col1,row2,col2 );
    return;
    /*
      首先看 能否 1 條線連接
      再看 能否 2 條線連接
      再看 能否 3 條線連接
      再看 能否 4 條線連接
      ...
      再看 能否 n 條線連接
    */
    console.log( "call searchRoad..." );
    if( row1 == -1 || col1 == -1 || row2 == -1 || col2 == -1 ){
      alert( "請選擇起點和終點..." );
      return;
    }
    // 嘗試 search1StraightLineRoad
    var roadList = search1StraightLineRoad( row1,col1,row2,col2 );
    if( roadList ){
      printRoad( roadList );
      return;
    }
    
    // 嘗試 search2StraightLineRoad
    roadList = search2StraightLineRoad( row1,col1,row2,col2 );
    if( roadList ){
      printRoad( roadList );
      return;
    }
    
    // 嘗試 search3StraightLineRoad
    roadList = search3StraightLineRoad( row1,col1,row2,col2 );
    if( roadList ){
      printRoad( roadList );
      return;
    }
    console.log( "there is no road between [ " + row1 + "," + col1 + " ] and [ " + row2 + "," + col2 + " ]" );
  }
 
  function search1StraightLineRoad(row1,col1,row2,col2){
      // 沒有通路返回 空
      // 有通路返回 集合( 哪怕路的長度爲 0 ,也要返回長度爲0的數組 )
      console.log( "call search1StraightLineRoad..." );
      //必然要求 同一行 或者 同一列
      if( row1 == row2 ){
          // 起點與終點在同一行
          // 檢查   row1行 中 col1 到 col2 之間有沒有障礙,即使只有一個障礙就算沒路
          var beginCol = col1;
          var endCol = col2;
          if( endCol < beginCol ){
              beginCol = col2;
              endCol = col1;
          }
          for( var col = beginCol + 1;col < endCol; col++ ){
              var className = getClassName( row1,col );
              if( className.indexOf( hinderClassNamePrefix ) == 0 ){
                  return null;
              } 
          }
          var roadList = [];
          for( var col = beginCol + 1;col < endCol; col++ ){
              roadList.push( [ row1,col ] );
          }
          return roadList;
      }else if( col1 == col2 ){
          // 起點與終點在同一列
          var beginRow = row1;
          var endRow = row2;
          if( endRow < beginRow ){
            beginRow = row2;
            endRow = row1;
          }
          for( var row = beginRow + 1;row < endRow; row++ ){
              var className = getClassName( row,col1 );
              if( className.indexOf( hinderClassNamePrefix ) == 0 ){
                  return null;
              } 
          }
          var roadList = [];
          for( var row = beginRow + 1;row < endRow; row++ ){
              roadList.push( [ row,col1 ] );
          }
          return roadList;
      }else{
          // 起點與終點既不在同一行也不再同一列
          return null;
      }
  }


  function findRoad3point( row1,col1,row2,col2,row3,col3 ){
      //下面三個條件得同時成立
      // row2,col2 是路
      if( getClassName( row2,col2 ).indexOf( hinderClassNamePrefix ) == 0 ){
          return null;
      }
      // 尋找  row1,col1 和 row2,col2 之間有沒有直線
      var roadList1 = search1StraightLineRoad( row1,col1,row2,col2 );
      if( !roadList1 ){
        return null;
      }
      // 尋找  row2,col2 和 row3,col3 之間有沒有直線
      var roadList2 = search1StraightLineRoad( row2,col2,row3,col3 );
      if( !roadList2 ){
        return null;
      }
      var  roadList =[];
      roadList.push( [ row2,col2 ] );
      for( var i in roadList1 ){
        roadList.push( roadList1[ i ] );
      }
      for( var i in roadList2 ){
        roadList.push( roadList2[ i ] );
      }
      return roadList;
  }


  function search2StraightLineRoad( row1,col1,row2,col2 ){
      // 該種走法必然是 該兩點所在的 舉行的兩條邊上,但是可以用一種簡單的方法
      // 以下兩個條件成立一個即可
      var roadList = findRoad3point( row1,col1,row1,col2,row2,col2 );
      if( roadList ){
          return roadList;
      }
      return findRoad3point( row1,col1,row2,col1,row2,col2 );
  }

  function clearLogo( row,col ){
      var className = $( $( $( "tr" )[ row ] ).children( "td" )[ col ] ).attr( "class" );
      $( $( $( "tr" )[ row ] ).children( "td" )[ col ] ).removeClass( className );
  }

  function getClassName( row,col ){
    return $( $( $( "tr" )[ row ] ).children( "td" )[ col ] ).attr( "class" );
  }

  function printRoad(roadList){
    for( var i in roadList ){
      var row = roadList[ i ][ 0 ];
      var col = roadList[ i ][ 1 ];
      var ele = $( $( $( "tr" )[ row ] ).children( "td" )[ col ] );
      ele.removeClass( hinderClassNamePrefix );
      ele.removeClass( "empty" );
      ele.addClass( "road" );
    }
  }

  function search3StraightLineRoad( row1,col1,row2,col2 ){
      // 選 一個  ( row1,col1 ) 可以到達的點 ,記作 ( row1_,col1_ ),則 點 ( row1,col1 ) 和 點( row1_,col1_ ) 可以 one  straight line  到達,
      // 如果 點 ( row1_,col1_ ) 和 點( row2,col2 ) 可以 two  straight line 達到,則 該任務順利完成
      // 其中 ( row1_,col1_ ) 代表 所有 ( row1,col1 )可以one  straight line 到達的點

      // 先向左搜索
      var row1_next = row1;
      var col1_next = col1;
      while( true ){
          col1_next--;
          if( col1_next < 0 ){
              break;
          }
          var className = getClassName( row1_next,col1_next );
          if( className.indexOf( hinderClassNamePrefix ) == 0 ){
              break;
          }
          var roadList = search2StraightLineRoad( row1_next,col1_next,row2,col2 );
          if( roadList ){
            // todo  將  ( row1,col1 ) 和  ( row1_next,col1_next ) 之間的點加入 roadList
            var roadListTemp = getOneStraightLineRoadListBetween( row1,col1,row1_next,col1_next );
            for( var i in roadListTemp ){
              roadList.push( [ roadListTemp[ i ][ 0 ],roadListTemp[ i ][ 1 ] ] );
            }
            roadList.push( [ row1_next,col1_next ] );
            return roadList;
          }
      }

      // 向右搜索
      row1_next = row1;
      col1_next = col1;
      while( true ){
          col1_next++;
          if( col1_next > ( colSize - 1 ) ){
              break;
          }
          var className = getClassName( row1_next,col1_next );
          if( className.indexOf( hinderClassNamePrefix ) == 0 ){
              break;
          }
          var roadList = search2StraightLineRoad( row1_next,col1_next,row2,col2 );
          if( roadList ){
            // todo  將  ( row1,col1 ) 和  ( row1_next,col1_next ) 之間的點加入 roadList
            var roadListTemp = getOneStraightLineRoadListBetween( row1,col1,row1_next,col1_next );
            for( var i in roadListTemp ){
              roadList.push( [ roadListTemp[ i ][ 0 ],roadListTemp[ i ][ 1 ] ] );
            }
            roadList.push( [ row1_next,col1_next ] );
            return roadList;
          }
      }

      // 向 上搜索
      row1_next = row1;
      col1_next = col1;
      while( true ){
          row1_next--;
          if( row1_next < 0 ){
              break;
          }
          var className = getClassName( row1_next,col1_next );
          if( className.indexOf( hinderClassNamePrefix ) == 0 ){
              break;
          }
          var roadList = search2StraightLineRoad( row1_next,col1_next,row2,col2 );
          if( roadList ){
            // todo  將  ( row1,col1 ) 和  ( row1_next,col1_next ) 之間的點加入 roadList
            var roadListTemp = getOneStraightLineRoadListBetween( row1,col1,row1_next,col1_next );
            for( var i in roadListTemp ){
              roadList.push( [ roadListTemp[ i ][ 0 ],roadListTemp[ i ][ 1 ] ] );
            }
            roadList.push( [ row1_next,col1_next ] );
            return roadList;
          }
      }

      //向下搜索
      row1_next = row1;
      col1_next = col1;
      while( true ){
          row1_next++;
          if( row1_next > ( rowSize - 1 ) ){
              break;
          }
          var className = getClassName( row1_next,col1_next );
          if( className.indexOf( hinderClassNamePrefix ) == 0 ){
              break;
          }
          var roadList = search2StraightLineRoad( row1_next,col1_next,row2,col2 );
          if( roadList ){
            // todo  將  ( row1,col1 ) 和  ( row1_next,col1_next ) 之間的點加入 roadList
            var roadListTemp = getOneStraightLineRoadListBetween( row1,col1,row1_next,col1_next );
            for( var i in roadListTemp ){
              roadList.push( [ roadListTemp[ i ][ 0 ],roadListTemp[ i ][ 1 ] ] );
            }
            roadList.push( [ row1_next,col1_next ] );
            return roadList;
          }
      }
      return null;
  }

  function getOneStraightLineRoadListBetween( row1,col1,row2,col2 ){
      var roadList = [];
      if( row1 == row2 ){
          var minCol = col1;
          var maxCol = col2;
          if( maxCol < minCol ){
            minCol = col2;
            maxCol = col1;
          }
          for( var col = minCol + 1;col < maxCol;col++ ){
            roadList.push( [ row1,col ] );
          }
      }else if( col1 == col2 ){
          var minRow = row1;
          var maxRow = row2;
          if( maxRow < minRow ){
            minRow = row2;
            maxRow = row1;
          }
          for( var row = minRow + 1;row < maxRow;row++ ){
            roadList.push( [ row,col1 ] );
          }
      }
      return roadList;
  }
</script>
</html>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章