2013-06-24 109 views
1

我試圖做一個簡單的(或者我以爲)記憶遊戲。不幸的是,當用戶點擊它們時,它不會更新卡的狀態。我正在用盡想法,可能是因爲這是我的第一個JavaScript遊戲。我猜遊戲循環有問題。任何人都可以至少指出我的方向是否正確,並幫助我理解需要更改/重寫的內容?簡單記憶遊戲不會更新其狀態。糟糕的遊戲循環?

//HTML5 Memory Game implementation 

//main variables 
var cards = [1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8]; 
var exposed = [makeArray("false",16)]; 
var first_card = 0; 
var second_card = 0; 
var moves = 0; 
var WIDTH = 800; 
var HEIGHT = 100; 
var state = 0; 
var mouseX = 0; 
var mouseY = 0; 

//creating canvas 
var canvas = document.createElement("canvas"); 
var ctx = canvas.getContext("2d"); 
canvas.width = WIDTH; 
canvas.height = HEIGHT; 
document.getElementById("game").appendChild(canvas); 

//filling empty array with number,character,object 
function makeArray(value, length) { 
    var newArray = []; 
    var i = 0; 
    while (i<length) { 
     newArray[i] = value; 
     i++; 
    } 
    return newArray; 
} 

//shuffling algorithm 
function shuffle(array) { 
    var copy = []; 
    var n = array.length; 
    var i; 

    while (n) { 
     i = Math.floor(Math.random() * n--); 
     copy.push(array.splice(i, 1)[0]); 
    } 

    return copy; 
} 

//where user clicks 
function getClickPosition(event) { 
    var X = event.pageX - canvas.offsetLeft; 
    var Y = event.pageY - canvas.offsetTop; 
    return mouse = [X, Y]; 
} 

//read click position 
function readPos(event) { 
    mousePos = getClickPosition(event); 
    mouseX = mousePos[0]; 
    mouseY = mousePos[1]; 
} 

//initializing 
function init() { 
    state = 0; 
    moves = 0; 
    exposed = [makeArray("false",16)]; 
    cards = shuffle(cards); 
} 

//drawing cards 
function draw() { 
    ctx.clearRect(0, 0, WIDTH, HEIGHT); 
    for (var i in cards) { 
     if (exposed[i] === true) { 
      ctx.fillStyle = "rgb(250, 250, 250)"; 
      ctx.font = "50px Courier New"; 
      ctx.fillText(cards[i], (i*50+12), 65); 
     } else { 
      ctx.strokeStyle = "rgb(250, 0, 0)"; 
      ctx.fillStyle = "rgb(0, 0, 250)"; 
      ctx.fillRect(i*50, 0, 50, 100); 
      ctx.strokeRect(i*50, 0, 50, 100); 
     } 
    } 
}; 

//update cards 
function update() { 
    if (exposed[parseInt(mouseX/50)] === false) { 
     if (state == 0) { 
      state = 1; 
      first_card = parseInt(mouseX/50); 
      exposed[parseInt(mouseX/50)] = true; 
     } else if (state == 1) { 
      state = 2; 
      second_card = parseInt(mouseX/50); 
      exposed[parseInt(mouseX/50)] = true; 
     } else { 
      if (cards[first_card] != cards[second_card]) { 
       exposed[first_card] = false; 
       exposed[second_card] = false; 
      } 
      state = 1; 
      first_card = parseInt(mouseX/50); 
      exposed[parseInt(mouseX/50)] = true; 
     } 
    } 
} 

addEventListener('click', readPos, false); 

setInterval(function() { 
    update(); 
    draw(); 
}, 16); 
+0

您是否嘗試過使用調試器來逐步瀏覽代碼並查看單擊時會發生什麼?您必須首先執行該操作,並將問題範圍縮小到無法按預期工作的那部分代碼。無論如何,這個過程應該可能導致你的解決方案,因爲它可能是微不足道的。祝你好運! – Mataniko

+0

檢查您的點擊事件是否真正被觸發(例如,在其中放置一個斷點或將一個console.log放入其中以及一些相關數據)。我懷疑有必要有16ms的間隔;這可能會造成積壓。如果你讓間隔更大(比如200毫秒),情況會有所改善嗎?你甚至可能想重新考慮一個循環,讓點擊卡片來更新界面。如果mouseX和mouseY被正確設置,檢查update()是否訪問同一個變量(例如它們是否具有相同的值?)。如果他們這樣做,它是否轉化爲正確的卡片(或卡片?)。 – Sumurai8

回答

0

副本後和粘貼代碼,我發現了幾件事:

  1. 你沒有一個事件偵聽器添加到任何東西,你應該把它添加到的東西,所以我說這記錄。
  2. 您使用值「false」初始化暴露的數組,然後檢查它們是否爲假。這些不一樣,字符串「假」不是布爾假。
  3. 您將已暴露的數組初始化爲多維數組[[false,false,false ...]],這應該是單維數組,因爲稍後您將檢查exposed [1](1取決於鼠標x的位置)
  4. 沒有必要要求繪製和更新每隔16毫秒,可以以後有人點擊調用它。
  5. 包裹了整個事情了一個功能,所以有沒有全局變量。

下面是代碼在改變了這些明顯的錯誤之後,可能會有優化的空間,但現在我已經解決了這些問題。

<!DOCTYPE html> 
<html> 
<head> 
<title>test</title> 
</head> 
<body> 
<div id="game"></div> 
<script type="text/javascript"> 

    (function(){ 
     //HTML5 Memory Game implementation 

     //main variables 
     var cards = [1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]; 
     var exposed = makeArray(false, 16); 
     var first_card = 0; 
     var second_card = 0; 
     var moves = 0; 
     var WIDTH = 800; 
     var HEIGHT = 100; 
     var state = 0; 
     var mouseX = 0; 
     var mouseY = 0; 

     //creating canvas 
     var canvas = document.createElement("canvas"); 
     var ctx = canvas.getContext("2d"); 
     canvas.width = WIDTH; 
     canvas.height = HEIGHT; 
     document.getElementById("game").appendChild(canvas); 

     //filling empty array with number,character,object 
     function makeArray(value, length) { 
      var newArray = []; 
      var i = 0; 
      while (i < length) { 
       newArray.push(value); 
       i++; 
      } 
      return newArray; 
     } 

     //shuffling algorithm 
     function shuffle(array) { 
      var copy = []; 
      var n = array.length; 
      var i; 

      while (n) { 
       i = Math.floor(Math.random() * n--); 
       copy.push(array.splice(i, 1)[0]); 
      } 

      return copy; 
     } 

     //where user clicks 
     function getClickPosition(event) { 
      var X = event.pageX - canvas.offsetLeft; 
      var Y = event.pageY - canvas.offsetTop; 
      return mouse = [X, Y]; 
     } 

     //read click position 
     function readPos(event) { 
      mousePos = getClickPosition(event); 
      mouseX = mousePos[0]; 
      mouseY = mousePos[1]; 
      update(); 
      draw(); 
     } 

     //initializing 
     function init() { 
      state = 0; 
      moves = 0; 
      exposed = makeArray(false, 16); 
      cards = shuffle(cards); 
     } 

     //drawing cards 
     function draw() { 
      ctx.clearRect(0, 0, WIDTH, HEIGHT); 
      for (var i in cards) { 
       if (exposed[i] === true) { 
        ctx.fillStyle = "rgb(150, 150, 150)"; 
        ctx.font = "50px Courier New"; 
        ctx.fillText(cards[i], (i * 50 + 12), 65); 
       } else { 
        ctx.strokeStyle = "rgb(250, 0, 0)"; 
        ctx.fillStyle = "rgb(0, 0, 250)"; 
        ctx.fillRect(i * 50, 0, 50, 100); 
        ctx.strokeRect(i * 50, 0, 50, 100); 
       } 
      } 
     }; 
     //update cards 
     function update() { 
      if (exposed[parseInt(mouseX/50)] === false) { 
       if (state == 0) { 
        state = 1; 
        first_card = parseInt(mouseX/50); 
        exposed[parseInt(mouseX/50)] = true; 
       } else if (state == 1) { 
        state = 2; 
        second_card = parseInt(mouseX/50); 
        exposed[parseInt(mouseX/50)] = true; 
       } else { 
        if (cards[first_card] != cards[second_card]) { 
         exposed[first_card] = false; 
         exposed[second_card] = false; 
        } 
        state = 1; 
        first_card = parseInt(mouseX/50); 
        exposed[parseInt(mouseX/50)] = true; 
       } 
      } 
     } 
     document.body.addEventListener('click', readPos, false); 
     init(); 
     draw(); 
    })(); 
</script> 
</body> 
</html> 
+0

非常感謝。我應該更多地關注我在代碼中寫的內容。我試圖從Python移植代碼,所以也許這也是原因。將所有內容都包含在函數中通常會更好嗎?還是隻是一種預防措施? – Aplegatt

+0

@Aplegatt它並不是所有的變量都在全球範圍內結束。不會真的做任何事情,但如果你的代碼需要與其他(人)的代碼一起運行,那麼通常不會污染全局範圍。你可以將所有東西包裝在一個名爲MemGame的函數中,用'this'在原型中定義var的函數,並將其用作構造函數來創建遊戲對象實例http://stackoverflow.com/questions/16063394/prototypical-繼承 - 寫作/ 16063711#16063711 – HMR

0

您的總體邏輯很好。
「壞」的一點是你處理事件的方式:事件處理程序應該存儲一些有價值的信息,該更新將在稍後處理和清除。
在這裏,您將更新與事件處理混合在一起,因爲事件不會在每次更新時觸發,所以無法使用 。

所以我做了一些小提琴給你看,主要的變化是 單擊事件處理程序,它更新了var last_clicked_card:

http://jsfiddle.net/wpymH/

//read click position 
function readPos(event) { 
    last_clicked_card = -1; 
    mousePos = getClickPosition(event); 
    mouseX = mousePos[0]; 
    mouseY = mousePos[1]; 
    // on canvas ? 
    if ((mouseY>100)||(mouseX<0)||(mouseX>WIDTH)) return; 
    // now yes : which card clicked ? 
    last_clicked_card = Math.floor(mouseX/50); 
} 

,然後更新的這個處理信息:

//update cards 
function update() { 
    // return if no new card clicked 
    if (last_clicked_card == -1) return; 
    // read and clear last card clicked 
    var newCard = last_clicked_card; 
    last_clicked_card=-1; 
    // flip, store it as first card and return 
    // if there was no card flipped 
    if (state==0) { exposed[newCard] = true; 
        first_card = newCard; 
        state = 1 ; 
        return;  } 
    // just unflip card if card was flipped 
    if ((state = 1) && exposed[newCard]) {  
        exposed[newCard]=false ; 
        state=0; 
        return; 
    } 
    // we have a second card now 
    second_card = newCard; 
    exposed[second_card] = true; 
    draw(); 
    // ... i don't know what you want to do ... 
    if (cards[first_card] == cards[second_card]) { 
     alert('win'); } 
    else { 
     alert('loose'); } 

    exposed[first_card]=false; 
    exposed[second_card]=false; 
    state=0; 

} 
+0

感謝您的幫助。 JavaScript中的這些事件處理程序讓我很頭疼。 – Aplegatt