2014-10-09 40 views
0

我寫了這個JavaScript應用程序15拼圖。整個應用程序包含在下面的文件中。每當我渲染一個新的棋盤時,我都會嘗試將初始配置存儲在'initialBoard'變量中,以便稍後重放相同的遊戲。然而,'initialBoard'變量似乎總是等於'currentBoard'變量。我是新來的JavaScript和任何幫助將不勝感激。拼圖故障 - 試圖保存初始板

<html> 
<head> 
    <title>15 Puzzle</title> 
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css"> 
    <style type="text/css"> 
     #puzzle-board { 
      border: 5px solid; 
     } 
     .puzzle-tile { 
      background:#fff; 
      background: -moz-linear-gradient(top, #fff, #eee); 
      background: -webkit-gradient(linear,0 0, 0 100%, from(#fff), to(#eee)); 
      box-shadow: inset 0 0 0 1px #fff; 
      -moz-box-shadow: inset 0 0 0 1px #fff; 
      -webkit-box-shadow: inset 0 0 0 1px #fff; 
      font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 
      font-size:60px; 
      height: 100px; 
      text-align: center; 
      text-decoration: none; 
      text-shadow:0 1px #fff; 
      user-select: none; 
      -moz-user-select: none; 
      -webkit-user-select: none; 
      -ms-user-select: none; 
      vertical-align:middle; 
      width: 100px; 
     } 

     #start-stop { 
      float: left; 
     } 

     #timer { 
      float: left; 
      margin-left: 10px; 
     } 

     #counter { 
      float: left; 
      margin-left: 10px; 
     } 
    </style> 
</head> 
<body> 
    <div class="container-fluid"> 
     <div class="row"> 
      <br /> 
     </div> 
     <div class="row"> 
      <div class="col-md-5 col-md-offset-1"> 
       <table id="puzzle"></table> 
      </div> 
      <div class="col-md-6"> 
       <div class="row"> 
        <br /> 
        <button type="button" class="btn btn-lg btn-success" id="start-stop">START</button> 
        <button type="button" class="btn btn-lg btn-default" id="timer"></button> 
        <button type="button" class="btn btn-lg btn-default" id="counter"></button> 
       </div> 
      </div> 
     </div> 
    </div> 
    <script src="http://code.jquery.com/jquery-1.11.0.min.js"></script> 
    <script src="http://code.jquery.com/ui/1.11.1/jquery-ui.min.js"></script> 
    <!--<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>--> 
    <script> 
     /** 
     * Puzzle Object 
     */ 
     puzzle = function(targetId) { 

      /************************************************************ 
      * Private members 
      ************************************************************/ 

      var 
       currentBoard, 
       initialBoard, 
       orderedBoard = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,'']]; 

      function canSwapTiles(source, target) { 
       var sourceTileRow = source.attr("data-row"); 
       var sourceTileCol = source.attr("data-col"); 
       var sourceTileValue = source.text(); 

       var targetTileRow = target.attr("data-row"); 
       var targetTileCol = target.attr("data-col"); 
       var targetTileValue = target.text(); 

       if (sourceTileValue != '' && targetTileValue != '') { 
        return false; 
       } else if (Math.abs(targetTileRow - sourceTileRow) > 1) { 
        return false; 
       } else if (Math.abs(targetTileCol - sourceTileCol) > 1) { 
        return false; 
       } else { 
        return true; 
       } 
      } 

      function swapTiles(source, target) { 
       var sourceTileRow = source.attr("data-row"); 
       var sourceTileCol = source.attr("data-col"); 
       var sourceTileValue = source.text(); 

       var targetTileRow = target.attr("data-row"); 
       var targetTileCol = target.attr("data-col"); 
       var targetTileValue = target.text(); 

       source.text(targetTileValue); 
       currentBoard[sourceTileRow][sourceTileCol] = parseInt(targetTileValue); 

       target.text(sourceTileValue); 
       currentBoard[targetTileRow][targetTileCol] = parseInt(sourceTileValue); 

       $(targetId).trigger('moved'); 

       console.log("swapped tiles"); 
       console.log(initialBoard); 

       if (isSolved()) 
       { 
        console.log('solved puzzle'); 
        console.log(initialBoard); 

        $(targetId).trigger('solved', { 
         board: initialBoard 
        }); 
       } 
      } 

      function renderBoard(board) { 
       $("#puzzle-board").empty(); 
       currentBoard = board; 
       //initialBoard = board; 

       console.log('rendering board'); 
       console.log(initialBoard); 

       for (i = 0; i < 4; i++) { 
        $("#puzzle-board").append('<tr class="puzzle-row" id="puzzle-row-' + i + '"></tr><br />'); 
        for (j = 0; j < 4; j++) { 
         var tile = '<td class="puzzle-tile" data-row="' + i + '" data-col="' + j + '">' + 
           board[i][j] + 
           '</td>'; 
         $("#puzzle-row-" + i).append(tile); 
        } 
       } 

       $(".puzzle-tile").draggable(
        { 
         revert: true, 
         snap: true, 
         snapMode: "inner", 
         zIndex: 100 
        } 
       ).droppable(
        { 
         drop: function (event, ui) { 
          var sourceTile = ui.draggable; 
          var targetTile = $(this); 

          if (canSwapTiles(sourceTile, targetTile)) { 
           swapTiles(sourceTile, targetTile); 
          } 
         } 
        } 
       ); 
      } 

      function randomBoard() { 
       var tileValues = []; 
       for (i = 0; i < 15; i++) { 
        tileValues[i] = i + 1; 
       } 

       var randomlyOrderedTileValues = ['']; 
       do { 
        randomlyOrderedTileValues[(16 - tileValues.length)] = tileValues.splice(Math.floor(Math.random() * tileValues.length), 1).pop(); 
       } while (tileValues.length > 0); 

       var board = []; 
       for (i = 0; i < 4; i++) { 
        board[i] = []; 
        for (j = 0; j < 4; j++) { 
         board[i][j] = randomlyOrderedTileValues.pop(); 
        } 
       } 
       return board; 
      } 

      function isSolved() { 
       for (i = 0; i < 4; i++) { 
        for (j = 0; j < 4; j++) { 
         if (isNaN(currentBoard[i][j])) 
         { 
          continue; 
         } 
         if (parseInt(currentBoard[i][j]) != parseInt(orderedBoard[i][j])) 
         { 
          return false; 
         } 
        } 
       } 
       return true; 
      } 

      /************************************************************ 
      * Constructor 
      ************************************************************/ 

      /* 
      * Initialize board 
      */ 
      $(targetId).append('<tbody id="puzzle-board"></tbody>'); 
      renderBoard(orderedBoard); 

      /************************************************************ 
      * Public data and methods 
      ************************************************************/ 

      return { 
       reset: function() { 
        renderBoard(orderedBoard); 
       }, 

       shuffle: function() { 
        //initialBoard = randomBoard(); 
        initialBoard = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,'',15]]; 
        renderBoard(initialBoard); 
       } 
      } 
     }; 

     /** 
     * Timer Object 
     */ 
     timer = function(targetId) { 

      /************************************************************ 
      * Private members 
      ************************************************************/ 

      var 
       intervalId, 
       totalSeconds = 0; 

      function pad(val) { 
       var valString = val + ""; 
       if (valString.length < 2) { 
        return "0" + valString; 
       } else { 
        return valString; 
       } 
      } 

      function setTime() 
      { 
       ++totalSeconds; 
       $("#seconds").html(pad(totalSeconds % 60)); 
       $("#minutes").html(pad(parseInt(totalSeconds/60))); 
      } 

      /************************************************************ 
      * Constructor 
      ************************************************************/ 

      /* 
      * Initialize timer 
      */ 
      $(targetId).append('<i>Time: &nbsp;</i><i id="minutes">00</i>:<i id="seconds">00</i>'); 

      /************************************************************ 
      * Public data and methods 
      ************************************************************/ 

      return { 
       reset: function() { 
        window.clearInterval(intervalId); 
        totalSeconds = 0; 
        $("#minutes").text('00'); 
        $("#seconds").text('00'); 
       }, 

       start: function() { 
        intervalId = window.setInterval(setTime, 1000); 
       }, 

       getTime: function() { 
        return pad(parseInt(totalSeconds/60)) + ':' + pad(totalSeconds % 60); 
       } 
      } 
     }; 

     /** 
     * Counter Object 
     */ 
     counter = function(targetId) { 

      /************************************************************ 
      * Private members 
      ************************************************************/ 

      var 
       steps = 0; 

      /************************************************************ 
      * Constructor 
      ************************************************************/ 

      /* 
      * Initialize timer 
      */ 
      $(targetId).append('<i id="steps-title">Steps: &nbsp;</i><i id="steps-count">0</i>'); 

      /************************************************************ 
      * Public data and methods 
      ************************************************************/ 

      return { 
       reset: function() { 
        steps = 0; 
        $("#steps-count").text(steps); 
       }, 

       incr: function() { 
        steps++; 
        $("#steps-count").text(steps); 
       }, 

       getSteps: function() { 
        return steps; 
       } 
      } 
     }; 

     $(document).ready(function() { 

      var Puzzle = puzzle("#puzzle"); 
      var Timer = timer("#timer"); 
      var Counter = counter("#counter"); 

      localStorage["games"] = '[]'; 

      $("#start-stop").click(function() { 
       switch ($(this).text()) { 
        case 'START': 
         $(this).removeClass("btn-success").addClass("btn-danger").text("STOP"); 
         Puzzle.shuffle(); 
         Timer.start(); 
         Counter.reset(); 
         break; 
        case 'STOP': 
         $(this).removeClass("btn-danger").addClass("btn-success").text("START"); 
         Puzzle.reset(); 
         Timer.reset(); 
         Counter.reset(); 
         break; 
       } 
      }); 

      $("#puzzle").bind('moved', 
       function(e, data) { 
        Counter.incr(); 
       } 
      ).bind('solved', 
       function(e, data) { 

        console.log(data); 

        $("#start-stop").removeClass("btn-danger").addClass("btn-success").text("START"); 
        Puzzle.reset(); 
        Timer.reset(); 
        Counter.reset(); 

       } 
      ); 
     }); 
    </script> 
</body> 

+0

在某人專門花時間和精力回答它之後刪除一個問題是不公平的。 – 2014-10-09 20:23:34

回答

1

當你調用Puzzle.shuffle()位置:

$("#start-stop").click(function() { 
    switch ($(this).text()) { 
     case 'START': 
      $(this).removeClass("btn-success").addClass("btn-danger").text("STOP"); 
      Puzzle.shuffle(); 
      Timer.start(); 
      Counter.reset(); 
      break; 
     case 'STOP': 
      $(this).removeClass("btn-danger").addClass("btn-success").text("START"); 
      Puzzle.reset(); 
      Timer.reset(); 
      Counter.reset(); 
      break; 
    } 
}); 

它初始化板,並將其傳遞到這裏renderBoard

shuffle: function() { 
    //initialBoard = randomBoard(); 
    initialBoard = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,'',15]]; 
    renderBoard(initialBoard); 
} 

然後renderBoard做到這一點:

currentBoard = board; 

這會導致兩個變量指向相同的對象。如果你想讓它們分開,那麼在renderBoard中你應該克隆該對象,而不是分配它。如果你使用jQuery的話,沿着這條線:

currentBoard = []; 
$.extend(currentBoard, board); 
+0

謝謝。我需要更好地學習語言。 – OnToTheNextOne 2014-10-09 16:56:08

+0

@OnToTheNextOne最好的學習方法是糾正錯誤:) – STT 2014-10-09 16:58:25

+0

對於我應該如何在這裏處理空的瓷磚,你有什麼建議嗎?我將它初始化爲一個空字符串,因爲這使得它易於渲染。但是之後它會成爲currentBoard數組中的NaN。我不得不添加一些尷尬的代碼來處理諸如isSolved()函數中的isNaN()檢查。 – OnToTheNextOne 2014-10-09 17:01:30