简单的记忆游戏;t更新其状态.糟糕的游戏循环

Simple memory game doesn't update its state. Bad game loop?

本文关键字:循环 状态 游戏 更新 记忆游戏 简单      更新时间:2023-09-26

我正在尝试制作一个简单的(或者我是这么想的)内存游戏。不幸的是,当用户点击卡片时,它不会更新卡片的状态。我没什么想法了,可能是因为这是我的第一个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);

我会检查您的addEventListener方法:https://developer.mozilla.org/en-US/docs/Web/API/EventTarget.addEventListener我还建议您考虑使用jQuery。

在复制并粘贴您的代码后,我发现了一些东西:

  1. 您并没有向任何内容添加事件侦听器,应该将其添加到某个内容中,所以我将其添加至文档中
  2. 使用值"false"初始化公开的数组,然后检查它们是否为false。它们不一样,字符串"false"不是布尔false
  3. 您将暴露的数组初始化为多维数组[[false,false,false…]]这应该是一维数组,因为稍后您将检查暴露的[1](1取决于鼠标x的位置
  4. 无需调用draw并每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>

您的整体逻辑很好
"糟糕"的一点是你处理事件的方式:事件处理程序应该存储一些有价值的信息更新将在稍后处理并清除
在这里,您将更新与事件处理混合在一起,这是不起作用的特别是因为该事件不会在每次更新时触发。

所以我做了一个小小提琴给你看,主要的变化是点击事件处理程序,它更新var last_clickd_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;
}