2014-04-27 61 views
0

我已經爲一個項目創建了一個JavaScript版本的掃雷,但我試圖引入一個額外的功能來更好地模擬我記得玩的桌面版本。 jsfiddle用於掃雷的JQuery網格遞歸(點擊相鄰的網格)

我有是「clickTile()」函數困難的特殊功能:

我完整的代碼可以在這裏找到。基本要求是將「已選」類以及相鄰礦的數量添加到所點擊圖塊的html中。我試圖解決的附加要求是遞歸自動刷新沒有相鄰地雷的地塊。

的功能,因爲它代表的是:

function clickTile($tile) { 
if ($tile.hasClass('mine')) { 
    alert('game over'); 
    $('.mine').css("background", "red"); 
} else if (!$tile.hasClass("selected")){ 
    mines = getNumberOfAdjacentMines($tile); 
    $tile.addClass("selected"); 
    $tile.html(mines); 

    //recursively call clickTile function as long as there are no adjacent mines 
    if (mines <= 0) { 

     height = $('#field .row').length; 
     width = $('#field .row .tile').length/height; 
     rowNum = $tile.parent().prevAll('div').length 
     colNum = $tile.prevAll('div').length 

     $above = $tile // td 
     .parent()  // tr 
     .parent()  // table or tbody 
     .children('.row') 
     .eq(rowNum - 1) // the row above this one 
     .children('.tile') 
     .eq(colNum) // in the same column as this 
     ; 

     $below = $tile // td 
     .parent()  // tr 
     .parent()  // table or tbody 
     .children('.row') 
     .eq(rowNum + 1) // the row below this one 
     .children('.tile') 
     .eq(colNum) // in the same column as this 
     ; 

     if (rowNum > 0) { 
      if (!$above.hasClass('mine') && !$above.hasClass('selected')){ 
       clickTile($above); 
      } 
     } 

     if (colNum < (width-1)){ 
      if(!$tile.next().hasClass('selected')) { 
       clickTile($tile.next()); 
      } 
     } 

     if (rowNum < (height-1)){ 
      if(!$below.hasClass('mine') && !$below.hasClass('selected')) { 
       clickTile($below); 
      } 
     } 

     if (colNum > 0){ 
      if (!$tile.prev().hasClass('selected')) { 
       clickTile($tile.prev()); 
      } 
     } 

    } 
} 


} 

對我來說,這應該工作遞歸點擊0相鄰礦山的所有瓷磚,但事實並非如此。任何人都可以幫助我理解我可能會因此而出錯嗎?行爲非常挑剔。

+0

它似乎按預期工作,你能詳細說明問題嗎? –

+0

再試幾次,有些情況下,它有太多的遞歸錯誤,它有一個錯誤 – juvian

+0

每個0應該有所有的瓦片上面,下面,左側和右側'點擊',但通常'下'瓷磚做沒有被點擊,我不知道爲什麼。 – gnp210

回答

1

與您的代碼的問題是這兩個變量不var關鍵字定義,所以它們在全球範圍內定義。

在clickTile功能,則應更換

// rowNum is defined in the global scope, 
// Its value is overwritten with each recursive call 
rowNum = $tile.parent().prevAll('div').length 

// rowNum has the function as a scope, 
// its keeps different rowNum values for each recursive function call 
var rowNum = $tile.parent().prevAll('div').length 

rowNum(和其他變量)的值由遞歸調用覆蓋,因此進一步的情況會出現錯誤的行爲

if (rowNum > 0) { // rowNum can be anything at this point 
    // The condition is randomly met 
} 

添加var keyw ord到你的變量,你的代碼應該按預期工作。

有關JavaScript範圍的更多信息here

+0

這太好了。正是我需要的。我有一段時間沒有編碼javascript,所以我完全忘記了它的範圍傾向。 – gnp210

1

那麼,你有一些選擇器的問題導致了太多的遞歸錯誤,有時候是無止境的循環。我試圖找到錯誤,並在某些情況下,您發送到遞歸點擊函數一個空選擇器,所以它沒有正常工作。我不喜歡這些選擇器,所以用我自己的方式獲取上面,下面,下一個和上一個元素,它工作的很好!下面是代碼:

function clickTile($tile) { 
var tiles=$(".tile"); 
var rows=8; 
var columns=8; 
var index=tiles.index($tile);  

if($tile.length ==0) return false; 
if ($tile.hasClass('mine')) { 
    alert('game over'); 
    $('.mine').css("background", "red"); 
} else if (!$tile.hasClass("selected")){ 
    mines = getNumberOfAdjacentMines($tile); 

    $tile.html(mines); 
    $tile.addClass("selected"); 

    //recursively call clickTile function as long as there are no adjacent mines 
    if (mines <= 0) { 

     if (index >= rows) { 
      $above=$(tiles.get(index-rows)); 
      if (!$above.hasClass('mine') && !$above.hasClass('selected')){ 
       clickTile($above); 
      } 
     } 

     if ((index+1)%columns !=0){ 
      $next=$(tiles.get(index+1)) 
      if(!$next.hasClass('selected')) { 
       clickTile($next); 
      } 
     } 

     if (index+rows < (rows*columns)){ 
      $below=$(tiles.get(index+rows)); 
      if(!$below.hasClass('mine') && !$below.hasClass('selected')) { 
       clickTile($below); 
      } 
     } 

     if ((index+1)%columns != 1){ 
      $prev=$(tiles.get(index-1)) 
      if (!$prev.hasClass('selected')) { 
       clickTile($prev); 
      } 
     } 

    } 
} 

}

,這裏是爲傳播鄰居較短的版本:

 if (mines <= 0) { 

      var posInRow=(index+1)%columns; 
      var neighbours=[]; 
      if(index >= rows) neighbours.push(index-rows);//up 
      if(index+rows < (rows*columns)) neighbours.push(index+rows);//down 
      if(posInRow != 0) neighbours.push(index+1);//right 
      if(posInRow != 1) neighbours.push(index-1);//left 
      for(var i=0;i<neighbours.length;i++){ 
       var neighbour=$(tiles.get(neighbours[i])); 
       if (!neighbour.hasClass('mine') && !neighbour.hasClass('selected')){ 
        clickTile(neighbour); 
       } 
      } 

     }