Javascript内存游戏-图像交换

Javascript memory game - image swapping

本文关键字:图像 交换 游戏 内存 Javascript      更新时间:2024-05-28

这是我正在开发的内存游戏的当前代码。我使用的是纯JavaScript,我的a标签的onclick函数有问题。我想要的是游戏将点击的图像(问号)与分配给点击图像的类名的图像进行交换,从而产生翻转效果。

我目前得到的是,无论我点击哪里,只有最后一个图像会被交换。

"use strict"
var newDiv = null;
var innerDiv = null;
var table = null;
var row = null;
var cell = null;
var aTag = null;
var image = null;
// Use this to put class names on the images.
var boxCounter = 0;
// Static memory-object.
var Memory = {
    memoryArray: [],
    init: function (e) {
        // Calls a separate js-file which generates a random numbers.
        Memory.memoryArray = RandomGenerator.getPictureArray(4, 4);
        // Calls the rendering method
        Memory.renderArray(Memory.memoryArray);
    },
    renderArray: function (myArray) {
        // Creates and places div-tags in the HTML-document.
        newDiv = document.createElement("div");
        document.getElementsByTagName("body")[0].appendChild(newDiv);
        innerDiv = document.createElement("div");
        newDiv.appendChild(innerDiv);
        // Creates a table and places it in the HTML-document.
        table = document.createElement("table");
        table.border = 1;
        // Generates rows and cells, swap the 4's to change the size of the gameboard.
        for (var i = 0; i < 4; ++i) {
            row = document.createElement("tr");
            table.appendChild(row);
            // Creates a cell, each with its own respective random number.
            for (var j = 0; j < 4; ++j) {
                cell = document.createElement("td");
                // Adds a "Question-mark"-picture to the cell and places them in a-tags.
                image = document.createElement("img");
                image.className = myArray[i * 4 + j];
                image.src = "https://github.com/1dv403/1dv403-laborationer/blob/master/3-gameon/memory/pics/0.png?raw=true";
                aTag = document.createElement("a");
                aTag.onclick = function () {
                    Memory.flipTile(image.className);
                };
                // Places the pictures in the document, along with its random number for easier testing purposes.
                aTag.appendChild(document.createTextNode(myArray[i * 4 + j]));
                aTag.appendChild(image);
                cell.appendChild(aTag);
                row.appendChild(cell);
            };
        };
        innerDiv.appendChild(table);
    },
    flipTile: function (imageClass) {
        console.log(imageClass);
        // This should flip the tiles if the number matches the class name.
        if (imageClass == 1) {
            image.src = "https://github.com/1dv403/1dv403-laborationer/blob/master/3-gameon/memory/pics/1.png?raw=true";
        };
        if (imageClass == 2) {
            image.src = "https://github.com/1dv403/1dv403-laborationer/blob/master/3-gameon/memory/pics/2.png?raw=true";
        };
        if (imageClass == 3) {
            image.src = "https://github.com/1dv403/1dv403-laborationer/blob/master/3-gameon/memory/pics/3.png?raw=true";
        };
        if (imageClass == 4) {
            image.src = "https://github.com/1dv403/1dv403-laborationer/blob/master/3-gameon/memory/pics/4.png?raw=true";
        };
        if (imageClass == 5) {
            image.src = "https://github.com/1dv403/1dv403-laborationer/blob/master/3-gameon/memory/pics/5.png?raw=true";
        };
        if (imageClass == 6) {
            image.src = "https://github.com/1dv403/1dv403-laborationer/blob/master/3-gameon/memory/pics/6.png?raw=true";
        };
        if (imageClass == 7) {
            image.src = "https://github.com/1dv403/1dv403-laborationer/blob/master/3-gameon/memory/pics/7.png?raw=true";
        };
        if (imageClass == 8) {
            image.src = "https://github.com/1dv403/1dv403-laborationer/blob/master/3-gameon/memory/pics/8.png?raw=true";
        };
    }
};
window.onload = Memory.init;

这是一个涉及闭包和循环的经典问题。考虑函数表达式创建的闭包

aTag.onclick = function () {
    Memory.flipTile(image.className);
};

它从更高的范围引用image,那么循环中的下一次迭代会发生什么?

image = document.createElement("img");

image现在指向不同的对象,因此在循环的最后一次迭代中,所有image都指向同一个(最后一个)<img>元素。

您需要为image创建一个闭包,这样就不会发生这种情况。你可以通过编写一个函数来生成你想要的函数

function makeClickListener(elm) {
    return function () {
        Memory.flipTile(elm.className);
    };
}

现在,使用它来创建点击监听器

aTag.onclick = makeClickListener(image);

这可以通过只传递字符串而不是整个对象来进一步优化(所需内存较少)。

所有的点击处理程序都引用相同的图像变量(在for循环结束后,它将是最后一个图像)。您需要每个处理程序引用不同的图像变量。您可以通过将其作为参数传递给函数来创建它的副本。

替换此:

function () {
  Memory.flipTile(image.className);
};

有了这个:

function(classname) {
  return function () {
    Memory.flipTile(className);
  };
}(image.classname);

第二个问题:全球形象。flipTile函数对一个图像变量做了一些事情,但里面没有声明

错误:

flipTile: function (imageClass) {

好:

flipTile: function (image, imageClass) {

现在,您还需要更改对传递图像的函数的调用:

function(img, classname) {
  return function () {
    Memory.flipTile(img, className);
  };
}(image, image.classname);

考虑到您将image作为参数传递给flipTile,似乎不需要传递image.classname,因此您可以将函数更改为使用image.classname。这一步骤是可选的,没有它代码应该可以正常工作。