对于上下文来说,这是针对经典的战舰游戏。
我有一个像这样的gameboard网格数组:
[[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
。
其次,我在某个地方出错了,我的函数没有返回一个2d数组,其中有任何对象,我只是接收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));