我正在尝试获得一个嵌套的forEach循环,它在二维数组中找到一对四。
这是我的数组的示例:
[0, 0, 0, 0, 0],
[0, 2, 0, 0, 0],
[0, 1, 2, 0, 0],
[0, 1, 2, 2, 0],
[1, 2, 1, 1, 2],
它应该忽略0并且只能找到四个带有'1'或'2'的条目的水平,垂直和对角线对。
有人有任何建议吗?
答案 0 :(得分:1)
我认为这是一个基本问题,它是许多棋盘游戏算法的核心,因此值得一般解决方案。
我的解决方案将返回n
个m*m
连续项目的坐标和值,这些项目可以在0
2D板上水平,垂直或对角存在。在这个2D板上,1
代表2
和m*m
表示相反值的空格。
基本思路是将n*n
板重新分段为n*n
重叠(按1项偏移)板块(块)。
我们拥有n
子板后,我们将获得可用行的多个n
数组用于水平,可用列的多个n
数组用于垂直和2 5*5
每个对角线的大小数组一个。
在我们的示例中,我们有一个var board = [[0, 0, 2, 0, 0],
[0, 2, 2, 0, 0],
[0, 1, 2, 0, 0],
[0, 1, 2, 2, 0],
[1, 1, 1, 1, 2]];
板,如下所示;
n
在这个板上左上角是(0,0),右下角是(4,4)。因此,如果我们的{ 'sx: 2, sy: 0, ex: 2, ey: 3': [ [ 2, 0 ], [ 2, 3 ], 2 ],
'sx: 0, sy: 4, ex: 3, ey: 4': [ [ 0, 4 ], [ 3, 4 ], 1 ],
'sx: 1, sy: 1, ex: 4, ey: 4': [ [ 1, 1 ], [ 4, 4 ], 2 ] }
值为4,您很快就会注意到我们应该期待三次点击,例如
结果在对象中返回如下;
sx
其中sy
和ex
表示起始(x,y)坐标,ey
和function checkBoard(b,n){
function chunk2D(b,n){
var chunks = [],
chunk;
if (!n || b.length < n || b[0].length < n ) return "no way..!";
for (var i = 0; i <= b.length - n; i++){
for (var j = 0; j <= b[0].length - n; j++){
chunk = {x:j, y:i, c:[]};
for (var k = 0; k < n; k++){
chunk.c.push(b[i+k].slice(j,j+n));
}
chunks.push(chunk);
chunk = [];
}
}
return chunks;
}
function getDiagonals(a){
var len = a.length,
result = [[],[]];
for (var i = 0; i < len; i++){
result[0].push(a[i][i]);
result[1].push(a[i][len-1-i]);
}
return result;
}
function getColumns(a){
return a.map((r,i) => r.map((_,j) => a[j][i]));
}
var chunks = chunk2D(b,n),
diags,
columns,
found;
return chunks.reduce(function(r,c,i){
diags = getDiagonals(c.c);
found = diags[0].reduce((p,d) => p !== 0 && d !== 0 && p == d ? d : 0);
found && (r["sx: " + c.x + ", sy: " + c.y + ", ex: " + (c.x+n-1) + ", ey: " + (c.y+n-1)] = [[c.x,c.y],[c.x+n-1,c.y+n-1],found]);
found = diags[1].reduce((p,d) => p !== 0 && d !== 0 && p == d ? d : 0);
found && (r["sx: " + c.x + ", sy: " + (c.y+n-1) + ", ex: " + (c.x+n-1) + ", ey: " + c.y] = [[c.x,c.y+n-1],[c.x+n-1,c.y],found]);
columns = getColumns(c.c);
columns.forEach(function(col,j){ // colums check
found = col.reduce((p,d) => p !== 0 && d !== 0 && p == d ? d : 0);
found && (r["sx: " + (c.x+j) + ", sy: " + c.y + ", ex: " + (c.x+j) + ", ey: " + (c.y+n-1)] = [[c.x+j,c.y],[c.x+j,c.y+n-1],found]);
});
c.c.forEach(function(row,j){ // rows check
found = row.reduce((p,d) => p !== 0 && d !== 0 && p == d ? d : 0);
found && (r["sx: " + c.x + ", sy: " + (c.y+j) + ", ex: " + (c.x+n-1) + ", ey: " + (c.y+j)] = [[c.x,c.y+j],[c.x+n-1,c.y+j],found]);
});
return r;
}, {});
}
var board = [[0, 0, 2, 0, 0],
[0, 2, 2, 0, 0],
[0, 1, 2, 0, 0],
[0, 1, 2, 2, 0],
[1, 1, 1, 1, 2]];
console.log(checkBoard(board,4));
表示属性中的结束(x,y)坐标。该值可供您进一步处理所有必需信息。
这是代码;
\s
&#13;
答案 1 :(得分:0)
var horizontal=[[0, 0, 0, 0, 0],[0, 2, 0, 0, 0],[0, 1, 2, 0, 0],[0, 1, 2, 2, 0],[1, 2, 1, 1, 2]];
var vertical=horizontal.reduce(function(arr,row)=>(row.forEach((el,i)=>arr[i].push(el)),arr),[]);
var result=[1,2].some(e=>horizontal.some(row=>row.filter(el=>el===e).length>=4))||vertical.some(row=>row.filter(el=>el===e).length>=4)));
只需计算每个方向每行中的一个和两个,如果有一些超过四个,则返回true。
答案 2 :(得分:0)
Jonas的回答比这个好得多,但如果你不理解他的语法,这里有一个简化的,更详细的版本:
var field = [
[0, 0, 0, 0, 0],
[0, 2, 0, 0, 0],
[0, 1, 2, 0, 0],
[0, 1, 2, 2, 0],
[1, 2, 1, 1, 2]
];
function checkVertical(field, player){
for(i = 0; i < 5; ++i){
if (field[0][i] === player
&& field[1][i] === player
&& field[2][i] === player
&& field[3][i] === player
) return true;
if (field[1][i] === player
&& field[2][i] === player
&& field[3][i] === player
&& field[4][i] === player
) return true;
}
return false;
}
function checkHorizontal(field, player){
for(i = 0; i < 5; ++i){
if (field[i][0] === player
&& field[i][1] === player
&& field[i][2] === player
&& field[i][3] === player
) return true;
if (field[i][1] === player
&& field[i][2] === player
&& field[i][3] === player
&& field[i][4] === player
) return true;
}
return false;
}
function checkDiagonal1(field, player){
// exercise for the reader
return false;
}
function checkDiagonal2(field, player){
// exercise for the reader
return false;
}
function isWin(field, player){
return checkVertical(field, player)
|| checkHorizontal(field, player)
|| checkDiagonal1(field, player)
|| checkDiagonal2(field, player);
}
console.log(isWin(field, 1));
答案 3 :(得分:0)
这是我使用基本的for循环和迭代来刺激它。我确信这不如@Red的例子那么有效。
每种类型的集都是一个单独的功能。输出采用坐标的形式,显示集合所在矩阵的位置,开始位置以及结束位置。显然,输出可以是布尔值或其他任何你想要的输出。我只是通过这种方式格式化输出以证明它有效。
我已经将过滤部分留给了用户,在这种情况下,我特意允许0(你的规范要求忽略它们),因为你的示例输入数据将永远不会返回水平或对角线调用的集合。下面的示例会筛选出包含少于4个元素的任何集合。
此示例假定行的长度都相同。如果行的长度不同,则需要更多逻辑。
const Matrix = function(matrix) { this.matrix = matrix; }
Matrix.prototype.getHorizontalSequences = function() {
const matrix = this.matrix, sets = [];
for(let i = 0; i < matrix.length; ++i) {
const row = matrix[i];
for(let j = 0; j < row.length; ++j) {
const start = j;
let k = j + 1;
for(; k < row.length; ++k) {
if(row[j] !== row[k]) break;
}
sets.push({ row: i, val: row[j], start: start, end: k - 1 });
j = k - 1;
}
}
return sets;
};
Matrix.prototype.getVerticalSequences = function() {
const matrix = this.matrix, sets = [];
for(let i = 0; i < matrix[0].length; ++i) {
for(let j = 0; j < matrix.length; ++j) {
const start = j;
let k = j + 1;
for(; k < matrix.length; ++k) {
if(matrix[j][i] !== matrix[k][i]) break;
}
sets.push({ col: i, val: matrix[j][i], start: start, end: k - 1 });
j = k - 1;
}
}
return sets;
};
Matrix.prototype.getDiagonalSequences = function() {
const matrix = this.matrix, sets = [];
for(let i = 0; i < matrix[0].length; ++i) {
for(let j = i; j < matrix.length; ++j) {
const start = j;
let k = j + 1;
for(; k < matrix.length; ++k) {
if(matrix[j][i] !== (matrix[j + k] || [])[i + k]) break;
}
sets.push({ col: i, val: matrix[j][i], start: start, end: k });
j = k - 1;
}
}
return sets;
};
let matrix = new Matrix([
[0, 0, 0, 0, 0],
[0, 2, 0, 0, 0],
[0, 1, 2, 0, 0],
[0, 1, 2, 2, 0],
[1, 2, 1, 1, 2]
])
console.log(matrix.getHorizontalSequences().filter(e => (e.end + 1) - e.start >= 4));
console.log(matrix.getVerticalSequences().filter(e => (e.end + 1) - e.start >= 4));
console.log(matrix.getDiagonalSequences().filter(e => (e.end + 1) - e.start >= 4));
.as-console-wrapper { max-height: 100% !important; }