如何在一个方阵中找到一个连续的符号序列

How to find a consecutive sequence of symbols in a squared matrix

本文关键字:一个 符号 连续 方阵中      更新时间:2023-09-26

我需要帮助找到正确的算法。我有一个二维数组,例如:

var arr = [
[""," "," "," ",""],
[""," "," "," ",""],
[""," "," ","X",""],
["","X","X","X",""],
[""," "," ","X",""]];

我想验证这个数组是否有三个在任何方向(水平或垂直,或交叉)上相互匹配的下一个符号,然后显示这些符号。

我是这样做的:

Run through array:

for(var i = 0; i < arr.length; i+=1){
   for(var j = 0; j < arr.length; j+=1){

验证是否匹配:

if(arr[i][j] == "X" && arr[i+1][j] == "X" && arr[i+2][j] == "X"){
       console.log(arr[i][j]);

但是它会给出一个错误,因为i+1i+2在数组后面。

我试着验证如果:

  if(arr[i][j+1] < arr.length)

但是它不计算最后一行

我该怎么做?

您可以尝试对每一行、每一列或每一条对角线进行连续计数。

给定一个阶跃函数,计算连续的"X"

data = {
    succX = 0
};
function step (data, arr, i, j) {
    data.succX = arr[i][j] === "X" ? data.succX + 1 : 0;
    return data.succX >= 3;;
}

然后,您可以迭代并查找步骤结果。如果step返回true,则存储相应的序列并停止搜索。

遍历每一行

for (var i = 0, nbRow = arr.length; i < nbRow; i++) {
    for (var j = 0, nbCol = arr[i].length; j < nbCol; j++) {
        data.winSeq = data.winSeq || step(data, arr, i, j) && [[i, j-2], [i, j-1], [i, j]];
    }
}
data.succX = 0;

遍历每一列

for (var j = 0, nbCol = arr[0].length; j < nbCol; j++) {
    for (var i = 0, nbRow = arr.length; i < nbRow; i++) {
        data.winSeq = data.winSeq || step(data, arr, i, j) && [[i-2, j], [i-1, j], [i, j]];
    }
}

遍历每个对角线

for (var d = 0, dim = arr.length, nbDiag = dim * 2 - 1; d < nbDiag; d++) {
    var maxE = d >= dim ? nbDiag - d - 1 : d;
    for (var e = 0; e <= maxE; e++) {
        var i = Math.min(d, dim -1) - e,
            j = Math.max(0, d - dim + 1) + e;
        data.winSeq = data.winSeq || step(data, arr, i, j) && [[i, j-2], [i+1, j-1], [i+2, j]];
    }
    data.succX = 0;
}
for (var d = 0, dim = arr.length, nbDiag = dim * 2 - 1; d < nbDiag; d++) {
    var maxE = d >= dim ? nbDiag - d - 1 : d;
    for (var e = 0; e <= maxE; e++) {
        var i = dim - 1 -Math.min(d, dim -1) + e,
            j = Math.max(0, d - dim + 1) + e;
        data.winSeq = data.winSeq || step(data, arr, i, j) && [[i-2, j-2], [i-1, j-1], [i, j]];
    }
    data.succX = 0;
}

最后,data.winSeq包含未定义序列或有效序列。

您可以在下面的代码片段中看到整个过程。

var delay = 0;
function findWinSeq(arr, seqLength) {
    var data = { succX: 0 };
    // Iteration step
    function step (data, arr, i, j) {
        if (arr[i][j] === "X") {
            data.succX++;
            colorize(i, j, "validCell", delay);
        } else {
            data.succX = 0;
            colorize(i, j, "selectCell", delay);
        }
        var hasWon = data.succX >= seqLength;
        delay += hasWon ? 2000 : 120;
        return hasWon;
    }
    // Count for each row
    for (var i = 0, nbRow = arr.length; i < nbRow; i++) {
        for (var j = 0, nbCol = arr[i].length; j < nbCol; j++) {
            data.winSeq = data.winSeq || step(data, arr, i, j) && [[i, j-2], [i, j-1], [i, j]];
        }
    }
    data.succX = 0;
    // Count for each column
    for (var j = 0, nbCol = arr[0].length; j < nbCol; j++) {
        for (var i = 0, nbRow = arr.length; i < nbRow; i++) {
            data.winSeq = data.winSeq || step(data, arr, i, j) && [[i-2, j], [i-1, j], [i, j]];
        }
    }
    // Count for each diagonal
    for (var d = 0, dim = arr.length, nbDiag = dim * 2 - 1; d < nbDiag; d++) {
        var maxE = d >= dim ? nbDiag - d - 1 : d;
        for (var e = 0; e <= maxE; e++) {
            var i = Math.min(d, dim -1) - e,
                j = Math.max(0, d - dim + 1) + e;
            data.winSeq = data.winSeq || step(data, arr, i, j) && [[i, j-2], [i+1, j-1], [i+2, j]];
        }
        data.succX = 0;
    }
    for (var d = 0, dim = arr.length, nbDiag = dim * 2 - 1; d < nbDiag; d++) {
        var maxE = d >= dim ? nbDiag - d - 1 : d;
        for (var e = 0; e <= maxE; e++) {
            var i = dim - 1 -Math.min(d, dim -1) + e,
                j = Math.max(0, d - dim + 1) + e;
            data.winSeq = data.winSeq || step(data, arr, i, j) && [[i-2, j-2], [i-1, j-1], [i, j]];
        }
        data.succX = 0;
    }
    return data.winSeq || null;
}
var tests = [
[
[" "," "," "," "," "],
    [" ","X"," ","X"," "],
    [" "," ","X"," "," "],
    [" "," "," ","X"," "],
    [" ","X"," "," "," "]
    ],
    [
    [" "," "," "," "," "],
    [" ","X"," ","X"," "],
    [" "," "," "," "," "],
    [" "," "," ","X"," "],
    [" ","X"," "," "," "]
    ],
    [
    [" "," "," "," "," "],
    [" ","X"," ","X"," "],
    [" "," "," "," ","X"],
    [" "," "," ","X"," "],
    [" ","X","X"," "," "]
    ],
    [
    [" "," "," "," "," "],
    [" "," "," ","X"," "],
    [" "," ","X","X"," "],
    [" "," "," ","X"," "],
    [" ","X"," "," "," "]
    ],
    [
    [" "," "," "," "," "],
    ["X","X","X","X"," "],
    [" "," ","X"," "," "],
    [" "," "," ","X"," "],
    [" ","X"," "," "," "]
    ],
    ];
// Just some fancy stuffs
function colorize(i, j, color, delay) {
    function _colorize(i, j, color) {
        // Reset first valid cell if needed
        if (color === "selectCell") {
            var cells = document.getElementsByClassName("validCell");
            for(var k = 0, cell; cell = cells[k]; k++) {
                cell.className = "cell";
            }
        }
        // Apply color to the next cell
        var previous = document.getElementsByClassName("selectCell")[0];
        if (previous !== undefined) { previous.className = "cell"; }
        document.getElementById([i,j].join("")).className = color;
    }
    setTimeout(_colorize, delay, i, j, color);
}
function buildBoard (test) {
    var board = document.getElementById("board");
    board.style.width = test.length * 40 + "px";
    board.innerHTML = "";
    for (var i = 0, marker, cell, dim = test.length; i < dim; i++) {
        for (var j = 0; j < dim; j++) {
            cell = document.createElement('div');
            cell.className = "cell";
            cell.id = [i,j].join("");
            if (test[i][j] === "X") {
                marker = document.createElement('div');
                marker.className = "marker";
                cell.appendChild(marker);
            }
            board.appendChild(cell);
        }
    }
}
for (var i = 0, test; test = tests[i]; i++) {
    setTimeout(function (test) {
        setTimeout(function (test) {
            buildBoard(test);
        }, delay, test);
        findWinSeq(test, 3);
    }, 750 * i, test);
}
#board {
    padding: 0;
    margin: 0;
    font-size: 0;
}
.cell, .validCell, .selectCell {
    display: inline-block;
    box-sizing: border-box;
    border: 1px solid #888;
    width: 40px;
    height: 40px;
}
.validCell {
    background: #CDEB8B;
}
.selectCell {
    background: #DDD;
}
.marker {
    background: #888;
    width: 16px;
    height: 16px;
    margin: 12px 0 0 12px;
}
<div id="board"></div>

你的循环应该在i < arr.length-2时停止,因为你想确保i+2在边界内。

三个连续的X符号由它们的中心和方向(水平、垂直或两条对角线之一)唯一定义。我会这样做(谢谢@DarthJS):

for (var i = 0; i < arr.length; i+=1) {
    for (var j = 0; j < arr.length; j+=1) {
        // Horizontal
        if (i > 0 && i < arr.length - 1 &&
            arr[i-1][j] == "X" && arr[i][j] == "X" && arr[i+1][j] == "X") {
            console.log(arr[i][j]);
        }
        // Vertical
        if (j > 0 && j < arr.length - 1 &&
            arr[i][j-1] == "X" && arr[i][j] == "X" && arr[i][j+1] == "X") {
            console.log(arr[i][j]);
        }
        // Diagonal
        if (i > 0 && i < arr.length - 1 &&
            j > 0 && j < arr.length - 1) {
            if (arr[i-1][j-1] == "X" && arr[i][j] == "X" && arr[i+1][j+1] == "X") {
                console.log(arr[i][j]);
            }
            if (arr[i-1][j+1] == "X" && arr[i][j] == "X" && arr[i+1][j-1] == "X") {
                console.log(arr[i][j]);
            }
        }
    }
}