I need help finding the right algorithm. I have a 2d array, for example:
var arr = [
[""," "," "," ",""],
[""," "," "," ",""],
[""," "," ","X",""],
["","X","X","X",""],
[""," "," ","X",""]];
And I want to verify if this array has three next symbols that match each other in any direction (horizontal or vertical, or cross), then display this symbols.
I'm doing it like this:
Run through array:
for(var i = 0; i < arr.length; i+=1){
for(var j = 0; j < arr.length; j+=1){
Then verify if match:
if(arr[i][j] == "X" && arr[i+1][j] == "X" && arr[i+2][j] == "X"){
console.log(arr[i][j]);
But it will give an error, because i+1
and i+2
are behind the array.
I've tried to make verification if:
if(arr[i][j+1] < arr.length)
But it doesn't count the last rows.
How can I do it?
当i < arr.length-2
,循环应该停止,因为您要确保i+2
在范围之内。
Three consecutive X symbols are uniquely defined by their center and the direction (horizontal, vertical or one of two diagonals). I'd do it like this (thanks @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]);
}
}
}
}
you can try to count successive for each row, column or diagonal.
data = {
succX = 0
};
function step (data, arr, i, j) {
data.succX = arr[i][j] === "X" ? data.succX + 1 : 0;
return data.succX >= 3;;
}
Then, you can iterate and look for step result. If step return true
, we might store the corresponding sequence and stop searching.
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;
}
At the end, data.winSeq
contains either undefined or a valid sequence.
You can see the whole process illustrated in the snippet right below.
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>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.