Javascript:检查周围的表格单元格

Jos*_*shK 9 html javascript css

我正在制作名为Dots and Boxes的游戏.

网格上有一堆点:

在此输入图像描述

<table>
    <tr>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
    </tr>
    <tr>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
    </tr>
</table>
Run Code Online (Sandbox Code Playgroud)

单击框的一侧时,它变为黑色:

在此输入图像描述 在此输入图像描述

function addLine(obj) {
            console.log("Called")

            if (obj.style.backgroundColor != "black") {
                obj.style.backgroundColor = "black";
                changeTurn()
            }
Run Code Online (Sandbox Code Playgroud)

一旦你点击第四面,关闭框,该框将改变点击第四面的玩家的颜色:

在此输入图像描述

目前,玩家必须手动点击该框以改变其颜色.但是,当盒子周围的四个边都是黑色的时候,我希望它能自动用颜色填充盒子.

如何在Javascript中使用函数来检查框的上方,下方,左侧和右侧的行是否填充为黑色?

var playerTurn = "Blue";
            changeTurn();
            var number = 0;

            function addLine(obj) {
                console.log("Called")

                if (obj.style.backgroundColor != "black") {
                    obj.style.backgroundColor = "black";
                    changeTurn()
                }
            }
            
            function fillBox(obj) {
                if (playerTurn == "Blue") {
                    obj.style.backgroundColor = "red";
                }
                else if ( playerTurn == "Red") {
                    obj.style.backgroundColor = "blue";
                }
            }

            function changeTurn() {
                if (playerTurn == "Red") {
                    playerTurn = "Blue";
                    document.getElementById('turn').style.color = "blue";

                }
                else if (playerTurn == "Blue") {
                    playerTurn = "Red";
                    document.getElementById('turn').style.color = "red";
                };
                console.log(playerTurn);
                document.getElementById('turn').innerHTML = playerTurn + "'s Turn";
            }
Run Code Online (Sandbox Code Playgroud)
h3 {
    font-family: Arial;
}
table {
    border-collapse: collapse;
}
.vLine {
    width: 10px;
    height: 60px;
}
.box {
    width: 60px;
    height: 60px;
}
.hLine {
    width: 60px;
    height: 10px;
}
.gap {
    width: 10px;
    height: 12px;
    background-color: black;
}
.vLine:hover, .hLine:hover {
    background-color: black;
}
Run Code Online (Sandbox Code Playgroud)
<h3 id="turn"></h3>

<table>
    <tr>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
    </tr>
    <tr>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
    </tr>
    <tr>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
    </tr>
    <tr>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
    </tr>
    <tr>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
    </tr>
    <tr>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
    </tr>
    <tr>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
    </tr>
    <tr>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
    </tr>
    <tr>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
    </tr>
    <tr>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
    </tr>
    <tr>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
    </tr>
    <tr>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
        <td class="box" onclick="fillBox(this)"></td>
        <td class="vLine" onclick="addLine(this)"></td>
    </tr>
    <tr>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
        <td class="hLine" onclick="addLine(this)"></td>
        <td class="gap"></td>
    </tr>
</table>
Run Code Online (Sandbox Code Playgroud)

Oka*_*Oka 3

这相当简单,但需要很好地使用 DOM 遍历。

当您单击一条线时,最多只能填写两个可能的框。对于水平线,这些框是上方和下方的框,这需要跳行。对于垂直线,左和右。

对于每个框,我们需要确认四行。同样,我们必须为上面和下面的行跳行。

实际上,我已经重新创建了这款游戏的大部分内容,因为它很有趣,而且这里有很多东西需要学习。那么让我们来看看重要的部分。我们将避免此代码中的不良形式,例如内联处理程序和直接在元素上设置样式,并且我们将让 CSS 类充当控件,尽管更完整的选项是data-attributes.

让我们从两个基本的辅助函数开始。

第一个用于将类似数组的对象转换为实际的数组,因此我们可以对Array.prototype它们使用方法。我们主要在物体上使用它nodeList。

function toArray (o) {
  return Array.prototype.slice.call(o);
}
Run Code Online (Sandbox Code Playgroud)

第二个利用第一个,并为我们提供元素在其 中的位置parentNode。

function nodeIndex (node) {
  return toArray(node.parentNode.children).indexOf(node);
}
Run Code Online (Sandbox Code Playgroud)

接下来是我们的事件处理程序。他们彼此非常相似。当我们单击一行时,我们用另一个辅助函数 填充该行,fill该函数将一个新类添加到名为 的行中.filled。然后我们检查可以填写的框。对于水平线,是上面和下面的垂直框;对于垂直线,这是水平框,左侧和右侧。我们删除了事件监听器,因此线条只能单击一次。

function addHLine (e) {
  fill(this);
  this.removeEventListener(e.type, addHLine);
  checkVerticalBoxes(this);
  updateGame();
}

function addVLine (e) {
  fill(this);
  this.removeEventListener(e.type, addVLine);
  checkHorizontalBoxes(this);
  updateGame();
}
Run Code Online (Sandbox Code Playgroud)

现在让我们看看checkHorizontalBoxes和checkVerticalBoxes。水平框位于同一行,+/-1从起始行开始索引。垂直框位于+/-1从起始行开始索引的行中,并与该行共享相同的索引。我们有一些if声明,因为有时可能的行或框会出界。

function checkHorizontalBoxes (line) {
  var left = line.previousElementSibling,
      right = line.nextElementSibling;

  if (left) checkSurroundingLines(left);
  if (right) checkSurroundingLines(right);
}

function checkVerticalBoxes (line) {
  var index = nodeIndex(line),
      up = line.parentNode.previousElementSibling,
      down = line.parentNode.nextElementSibling;

  if (up) checkSurroundingLines(up.children[index]);
  if (down) checkSurroundingLines(down.children[index]);
}
Run Code Online (Sandbox Code Playgroud)

这两个函数都会调用checkSurroundingLines潜在的盒子。该函数调用另外两个函数 -checkVerticalLines和checkHorizontalLines。开始看到规律了吗?isFilled与 类似fill,它是我们定义的一个辅助函数,用于测试一行是否具有该类.filled。

function checkHorizontalLines (node, idx) {
  var left = node.previousElementSibling,
      right = node.nextElementSibling;

  return isFilled(left) && isFilled(right);
}

function checkVerticalLines (node, idx) {
  var row = node.parentNode,
      up = row.previousElementSibling.children[idx],
      down = row.nextElementSibling.children[idx];

  return isFilled(up) && isFilled(down);
}
Run Code Online (Sandbox Code Playgroud)

如果这两个都返回,true我们将填写我们的框。


这是这种 DOM 遍历逻辑的基本概述。实际代码中有一些额外的内容,因此请阅读所有部分。

这是工作游戏:

DEMO

function toArray (o) {
  return Array.prototype.slice.call(o);
}
Run Code Online (Sandbox Code Playgroud)
function nodeIndex (node) {
  return toArray(node.parentNode.children).indexOf(node);
}
Run Code Online (Sandbox Code Playgroud)
function addHLine (e) {
  fill(this);
  this.removeEventListener(e.type, addHLine);
  checkVerticalBoxes(this);
  updateGame();
}

function addVLine (e) {
  fill(this);
  this.removeEventListener(e.type, addVLine);
  checkHorizontalBoxes(this);
  updateGame();
}
Run Code Online (Sandbox Code Playgroud)