使用 Array.prototype.map 将带有索引的对象插入到二维数组中
using Array.prototype.map to insert object with index into 2D array
对于上下文,这是针对经典战舰游戏的。
我有一个像这样的游戏板网格阵列:
[[null, null, null, null, null],
[null, null, null, null, null],
[null, null, null, null, null],
[null, null, null, null, null],
[null, null, null, null, null]],
我正在尝试将一个 ship
对象放入数组中。该对象由一些属性组成,例如船的name
、length
和index
(以便在船对象上标记船被击中的位置)。例如,放在第一行的船可能如下所示:
[null, {name: 'boat' , index: 0 }, {name: 'boat' , index: 1 }, null, null]
我想使用函数式编程原则来实现这一点并避免改变数组,这正是我目前正在做的(即使用 for 循环和设置 array[x][y] = {ship}
)。
我知道实现此目的的最佳方法是使用 map()
。
由于数组是二维的,所以我将两个地图嵌套在一起。到目前为止,我的功能如下所示:
const placeShip = (ship, x, y) => {
if (grid[x][y] !== null) return;
const newGrid = grid.map((row, indexX) => row.map((element, indexY) => {
if (indexX === x && indexY === y) {
{
name: ship.name,
index: XXX
} // how to insert the index position?
}
}
return newGrid
}
我遇到的麻烦是双重的。首先,我无法弄清楚如何使用嵌套地图将船舶的索引位置正确插入对象中。使用 for
循环非常简单,因为它们从 0
开始并在 ship.length
结束。
其次,我哪里出错了,我的函数没有返回一个包含任何对象的二维数组,我只是收到 undefined
.
我哪里错了?
谢谢
如果你只考虑水平放置的船只,你可以像这样检查船只是否出现在瓷砖上:
ri === r && // The ship sails on the current row
ci >= c && // The start of the ship lies left of this column
ci < c + size // The end of the ship lies right of this column
然后,0
和 shipSize
之间的索引可以使用以下公式计算:ci - c
这是一个简化的例子:
const grid = Array.from(Array(4), () => Array(4).fill("~~"));
const placeShipH = (r, c, size, name, grid) => grid.map(
(row, ri) => row.map(
(col, ci) => ri === r && ci >= c && ci < c + size
? `${name}${ci - c + 1}`
: col
)
);
const placeShipV = (r, c, size, name, grid) => grid.map(
(row, ri) => row.map(
(col, ci) => ci === c && ri >= r && ri < r + size
? `${name}${ri - r + 1}`
: col
)
);
const gridToString = grid => grid.map(row => row.join(" ")).join("\n");
const afterShipA = placeShipH(1, 1, 2, "A", grid);
const afterShipB = placeShipH(3, 0, 3, "B", afterShipA);
const afterShipC = placeShipV(0, 3, 3, "C", afterShipB)
console.log(gridToString(afterShipC));
对于上下文,这是针对经典战舰游戏的。
我有一个像这样的游戏板网格阵列:
[[null, null, null, null, null],
[null, null, null, null, null],
[null, null, null, null, null],
[null, null, null, null, null],
[null, null, null, null, null]],
我正在尝试将一个 ship
对象放入数组中。该对象由一些属性组成,例如船的name
、length
和index
(以便在船对象上标记船被击中的位置)。例如,放在第一行的船可能如下所示:
[null, {name: 'boat' , index: 0 }, {name: 'boat' , index: 1 }, null, null]
我想使用函数式编程原则来实现这一点并避免改变数组,这正是我目前正在做的(即使用 for 循环和设置 array[x][y] = {ship}
)。
我知道实现此目的的最佳方法是使用 map()
。
由于数组是二维的,所以我将两个地图嵌套在一起。到目前为止,我的功能如下所示:
const placeShip = (ship, x, y) => {
if (grid[x][y] !== null) return;
const newGrid = grid.map((row, indexX) => row.map((element, indexY) => {
if (indexX === x && indexY === y) {
{
name: ship.name,
index: XXX
} // how to insert the index position?
}
}
return newGrid
}
我遇到的麻烦是双重的。首先,我无法弄清楚如何使用嵌套地图将船舶的索引位置正确插入对象中。使用 for
循环非常简单,因为它们从 0
开始并在 ship.length
结束。
其次,我哪里出错了,我的函数没有返回一个包含任何对象的二维数组,我只是收到 undefined
.
我哪里错了?
谢谢
如果你只考虑水平放置的船只,你可以像这样检查船只是否出现在瓷砖上:
ri === r && // The ship sails on the current row
ci >= c && // The start of the ship lies left of this column
ci < c + size // The end of the ship lies right of this column
然后,0
和 shipSize
之间的索引可以使用以下公式计算:ci - c
这是一个简化的例子:
const grid = Array.from(Array(4), () => Array(4).fill("~~"));
const placeShipH = (r, c, size, name, grid) => grid.map(
(row, ri) => row.map(
(col, ci) => ri === r && ci >= c && ci < c + size
? `${name}${ci - c + 1}`
: col
)
);
const placeShipV = (r, c, size, name, grid) => grid.map(
(row, ri) => row.map(
(col, ci) => ci === c && ri >= r && ri < r + size
? `${name}${ri - r + 1}`
: col
)
);
const gridToString = grid => grid.map(row => row.join(" ")).join("\n");
const afterShipA = placeShipH(1, 1, 2, "A", grid);
const afterShipB = placeShipH(3, 0, 3, "B", afterShipA);
const afterShipC = placeShipV(0, 3, 3, "C", afterShipB)
console.log(gridToString(afterShipC));