【问题标题】:Interactions between adjacent td相邻 td 之间的相互作用
【发布时间】:2019-02-16 23:37:48
【问题描述】:

问题

由于它们的坐标,我如何比较两个相邻的单元格?

对我有帮助的文档

我已经看到了这些问题,它们帮助了我,但它们与我的情况不同:

  1. question on stackOverflow
  2. question on stackOverflow
  3. question on stackOverflow
  4. Mds documentation to build a dynamic table

代码

我有一个动态生成的表格

function tableGenerate(Mytable){
        for(var i = 0; i < myTable.length; i++) {
            var innerArrayLength = myTable[i].length;
            for(var j = 0; j<innerArrayLength; j++){
                if(myTable[i][j] === 0){
                    myTable[i][j]="x";
                }else{
                    myTable[i][j]="y";
                };
            };
            $("#aTable").append("<tr><td>"+ myTable[i].join('</td><td>') + "</td></tr>")    
        }
}  

关于actualPositionrowcell中感兴趣的单元格(两个全局变量)有随机值

var mainTd = {
     name: 'interestedValue',
     actualPosition:{
            row: 5,
            cell: 4
          }
};

var otherMainTd = {
     actualPosition:{
            row: 2,
            cell: 3
          }
};

代码的最后部分是这样工作的:

  • 我将 selectedTd 的位置保存在两个不同的变量中
  • 我创建了二维数组directions,其坐标是与selectedTd 相关的邻近单元格的坐标
  • 输入第一个if,比较两个单元格。如果其中一个坐标相同,则输入最后一个if

function compare(selectedTd) {
    let tdRow = selectedTd.actualPosition.row;
    let tdCell = selectedTd.actualPosition.cell;
    let directions = [
        [tdRow - 1, tdCell],
        [tdRow + 1, tdCell],
        [tdRow, tdCell + 1],
        [tdRow, tdCell - 1]
    ]; //these are the TD near the mainTd, the one i need to compare to the others

    let tdToCompare = [];

    if (selectedTd.name === 'interestedValue') {
        tdToCompare = [otherMainTd.actualPosition.row, otherMainTd.actualPosition.cell];
        for (let i = 0; i < directions.length; i++) {
            if (directions[i] == tdToCompare) {
                console.log('you are here');
            }
        }
    } else {
        tdToCompare = [mainTd.actualPosition.row, mainTd.actualPosition.cell];
        for (let i = 0; i < directions.length; i++) {
            if (directions[i] === tdToCompare) {
                console.log('you are here');
            }
        }
    }
};

现在的主要问题是:我读取了坐标,我将它们存储在 2 个数组中,我可以读取它们但我无法输入 if 语句。

这就是我想要实现的:将blackTd 的坐标与红色边框td 的坐标进行比较。

Codepen

codepen 中感兴趣的函数名称不同,但结构与您在本文中看到的相同。我更改了原始名称,因为我认为使用通用名称而不是我选择的名称可能会更清楚。

感兴趣的函数是:

  • function fight(playerInFight) ---> function compare(selectedTd)
  • function mapGenerate(map) ---> function tableGenerate(MyTable)
  • mainTdotherMainTd ---> charactercharacterTwo

CodepenHere

【问题讨论】:

  • 您正在混合 == 和 ===。请记住,他们不会做同样的事情。使用 == 除非您还需要比较变量的类型。如果您有兴趣,您会提到一个,但不太清楚您指的是哪一个。一共有三个,我猜是第一个,但最好指出哪个是
  • 您的代码足够复杂,我建议您在 Fiddle 或类似服务上创建一个工作演示。
  • @JaviMollá - 始终建议使用===
  • 哦,对不起。我完全错了。谢谢指出
  • @Legeo 只是一个建议/评论。创建表时,将td 内容分配给一个变量。然后,在 for 的末尾,将内容添加到 DOM。运行这一行$("#aTable").append("&lt;tr&gt;&lt;td&gt;"+ myTable[i].join('&lt;/td&gt;&lt;td&gt;') + "&lt;/td&gt;&lt;/tr&gt;") 每一行,对浏览器的影响很大,因为您在每次迭代时都在更改 DOM。

标签: javascript jquery arrays html-table


【解决方案1】:

更新: 再次阅读您的代码,我想我找到了问题所在。您正在比较数组 instances 而不是它们的实际值。看这个简单的例子来说明这个问题:

var a = [1];
var b = [1];

console.log(a===b);

您需要在代码中执行以下操作:

 if (selectedTd.name === 'interestedValue') {
    tdToCompare = [otherMainTd.actualPosition.row, otherMainTd.actualPosition.cell];
    for (let i = 0; i < directions.length; i++) {
        if (
          directions[i][0] === tdToCompare[0] &&
          directions[i][1] === tdToCompare[1]
        ) {
            console.log('you are here');
        }
    }
} else {
    tdToCompare = [mainTd.actualPosition.row, mainTd.actualPosition.cell];
    for (let i = 0; i < directions.length; i++) {
        if (
          directions[i][0] === tdToCompare[0] &&
          directions[i][1] === tdToCompare[1]
        ) {
            console.log('you are here');
        }
    }
}

现在它检查值是否匹配,从而检查单元格是否匹配。


建议:

如果我是你,我会写一些不同的方法。下面是我的做法。

function compare(selectedTd) {
  const
    // Use destructuring assignemnt to get the row and cell. Since these are 
    // values that won't be changed in the method declare them as "const". Also
    // drop the "td" prefix, it doesn't add anything useful to the name.
    // See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment  
    { row, cell } = selectedTd.actualPosition,
    
    // Directions can also be a const, it will not be reassigned in the method.
    directions = [
        [row - 1, cell],
        [row + 1, cell],
        [row, cell + 1],
        [row, cell - 1]
    ],
    // A few things happens in this line:
    // - It is a destructuring assignment where the names are changed. In this case 
    //   row and cell are already assigned so it is necessary to give them another name.
    // - Don't put the row and cell in an array. You will have to access the actual values
    //   anyway as you can't compare the array instances.
    // - Instead of doing this in the if…else you had, decide here which cell you want to
    //   look for. It means the rest of the method can be written without wrapping any
    //   logic in an if…else making it less complex.
    { row: referenceRow, cell: referenceCell } = (selectedTd.name === 'interestedValue')
      ? otherMainTd.actualPosition
      : mainTd.actualPosition,
    
    // Use find instead of a for loop. The find will stop as soon as it finds a match. The
    // for loop you had kept evaluating direction items even if the first one was already
    // a match.
    // The "([row,cell])" is the signature of the callback method for the find. This too is
    // a destructuring assignment only this time with one of the arrays of the directions
    // array. The first array item will be named "row" and the second item "cell". These
    // variable names don't clash with those declared at the top of this method as this
    // is a new scope.
    // The current directions entry is a match when the row and cell values match.
    matchingNeighbor = directions.find(([row, cell]) => row === referenceRow && cell === referenceCell);
    
    // "find" returns undefined when no match was found. So when match is NOT unddefined
    // it means directions contained the cell you were looking for.
    if (matchingNeighbor !== undefined) {
      console.log('you are here');    
    }
};

const
  mainTd = {
    name: 'interestedValue',
    actualPosition: {
      cell: 1,
      row: 1
    }
  },
  otherMainTd = {
    actualPosition: {
      cell: 0,
      row: 1
    }
  };

compare(mainTd);

原始答案:

您的问题有很多内容,我希望我理解正确。

我所做的是创建一个网格,您将尺寸传递给它,它将为网格中的每个单元格创建数组。然后它返回一个对象,其中包含一些可用于与网格交互的方法。它有以下几种方法:

  • cellAtCoordinate:传递 X 和 Y 坐标,它返回单元格。
  • isSameLocation:将两个单元格传递给它,它会检查单元格是否在同一个位置。
  • neighborsForCoordinate:传递一个 X 和 Y 坐标,它会返回一个数组,其中包含上、下、右、左(如果存在)的单元格。

排除了所有这些,比较方法变得更易于管理。获取邻居现在只是一个调用,检查两个单元格是否匹配也是如此。

就像我说的,我希望这就是你想要实现的目标。如果我的问题有误并且需要进一步解释,请告诉我。

/**
 * Creates grid with the provided dimensions. The cell at the top left corner
 * is at coordinate (0,0). The method returns an object with the following 
 * three methods:
 * - cellAtCoordinate
 * - isSameLocation
 * - neighborsForCoordinate
 */
function Grid(width, height) {
  if (width === 0 || height === 0) {
    throw 'Invalid grid size';
  }
  
  const
    // Create an array, each item will represent a cell. The cells in the
    // array are laid out per row.
    cells = Array.from(Array(width * height), (value, index) => ({
      x: index % width,
      y: Math.floor(index / height)
    }));
    
  function cellAtCoordinate(x, y) {
    // Make sure we don't consider invalid coordinate
    if (x >= width || y >= height || x < 0 || y < 0) {
      return null;
    }

    // To get the cell at the coordinate we need to calculate the Y offset
    // by multiplying the Y coordinate with the width, these are the cells
    // to "skip" in order to get to the right row.
    return cells[(y * width) + x];
  }
  
  function isSameLocation(cellA, cellB) {
    return (
      cellA.x === cellB.x &&
      cellA.y === cellB.y
    );
  }

  function neighborsForCoordinate(x, y) {
    // Make sure we don't consider invalid coordinate
    if (x >= width || y >= height || x < 0 || y < 0) {

      return null;
    }
    const
      result = [];

    // Check if there is a cell above.
    if (y > 0) result.push(cellAtCoordinate(x, y - 1));
    // Check if there is a cel to the right
    if (x < width) result.push(cellAtCoordinate(x + 1, y));
    // Check if there is a cell below.
    if (y < height) result.push(cellAtCoordinate(x, y + 1));
    // Check if there is a cell to the left.
    if (x > 0) result.push(cellAtCoordinate(x - 1, y));

    return result;
  }

  return {
    cellAtCoordinate,
    isSameLocation,
    neighborsForCoordinate
  }
}

function compareCells(grid, selectedCell) {
  const
    // Get the neighbors for the selected cell.
    neighbors = grid.neighborsForCoordinate(selectedCell.x, selectedCell.y);
    compareAgainst = (selectedCell.name === 'interestedValue')
      ? otherMainTd
      : mainTd;
      
    // In the neighbors, find the cell with the same location as the cell
    // we want to find.
    const
      match = neighbors.find(neighbor => grid.isSameLocation(neighbor, compareAgainst));
      
    // When match is NOT undefined it means the compareAgainst cell is
    // a neighbor of the selected cell.
    if (match !== undefined) {
      console.log(`You are there at (${match.x},${match.y})`);
    } else {
      console.log('You are not there yet');
    }      
}

// Create a grid which is 3 by 3.
const
  myGrid = Grid(3, 3),
  // Place the main TD here:
  // - | X | -
  // - | - | -
  // - | - | -
  mainTd = {
    name: 'interestedValue',
    x: 1,
    y: 0
  },
  // Place the other TD here:
  // - | - | -
  // Y | - | -
  // - | - | -  
  otherMainTd = {
    x: 0,
    y: 1
  };


// Check if the mainTd is in a cell next to the otherMainTd. It is not
// as the neighboring cells are:
// N | X | N
// Y | N | -
// - | - | -

compareCells(myGrid, mainTd);
// Move the mainTd to the center of the grid
// - | - | -
// Y | X | -
// - | - | -
mainTd.y = 1;

// Compare again, now the main TD is next the the other.
// -  | N | -
// YN | X | N
// -  | N | -
compareCells(myGrid, mainTd);

【讨论】:

  • 对于问题的质量,我很抱歉,我已尽力解释。我能问一下最难理解的部分是什么吗?所以我可以试着改变一下。如果你打开 codepen,你会看到一个带有地图的小游戏,它是随机生成的。现在我需要了解一个角色何时靠近另一个角色以开始一些基本的交互。我认为使用 td 的坐标是最好的方法。主要问题是我无法比较存储在数组中的值,我不明白为什么。
  • 更新了我的答案,我想我找到了问题。
  • 我更好地阅读了您的答案,明白了。谢谢你的解释,真的很清楚了。
  • 我现在还有一些时间,所以我再次更新了我的答案。我重写了你的比较方法并解释了为什么我会做不同的事情。我看了你的游戏,看起来不错,干得好!我确实认为您的 JS 可以从一些更好的结构中受益。至于是什么让你的问题难以回答,对我来说,这是缺乏示例输入。您从地图生成方法开始,然后是一些数据结构,最后是您需要帮助的方法。大量信息与问题无关。在许多情况下,一个好的问题包含示例输入、代码和预期输出。
  • 这是我在堆栈溢出中收到的最佳答案。您的解释非常详尽,我非常感谢您付出的所有努力。我还需要一个小时来给你赏金。感谢所有的解释,它们对我来说意义重大。
猜你喜欢
  • 2018-05-23
  • 2018-04-22
  • 2020-04-11
  • 1970-01-01
  • 1970-01-01
  • 2013-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多