数组内部边界的条件
我有一个矩阵,我有一个函数可以使用以下代码随机选择数组中的一个元素:
npcSelectShip() {
let selectCol = () => {
let colIndex = Math.floor(Math.random() * this.npcSelectionField.length);
let selectCell = () => {
let cellIndex = Math.floor(Math.random() * this.npcSelectionField[colIndex].length);
if (this.npcSelectionField[colIndex][cellIndex].isEmpty === false) {
selectCell();
} else {
this.npcSelectionField[colIndex][cellIndex].isEmpty = false;
this.pickDirection(this.npcSelectionField, colIndex, cellIndex);
}
}
selectCell();
}
selectCol();
}
在此之后,我有另一个函数,它搜索随机挑选元素的邻居(顶部、右侧、底部和左侧),随机挑选一个邻居并更改属性:
pickDirection(field, col, cell) {
let neighbors = [];
neighbors.push(
field[col - 1][cell],
field[col + 1][cell],
field[col][cell - 1],
field[col][cell + 1]
);
let randDir = () => {
let randIndex = neighbors[Math.floor(Math.random() * neighbors.length)];
if (randIndex.isEmpty === false) {
randDir();
} else {
randIndex.isEmpty = false;
}
}
randDir();
}
我面临的问题是当随机挑选的元素的索引为 0 或等于数组长度时,因为如果它在索引 -1 或索引 +1 处挑选一个邻居,它基本上是“超出范围”的,我得到这些错误:
TypeError: Cannot read property 'isEmpty' of undefined
TypeError: Cannot read property '9' of undefined
有没有办法可以解决这个问题,而不必编写大量的 if 和 else?
感谢您的帮助。
您可以使用
Array.concat
和默认模式,该模式返回一个空数组。
与
concat
结合使用时,空数组可用作中性值。
var neighbors = [].concat(
(field[col - 1] || [])[cell] || [],
(field[col + 1] || [])[cell] || [],
(field[col] || [])[cell - 1] || [],
(field[col] || [])[cell + 1] || []
);
或者使用包装器来访问
function getCell(array, col, cell) {
return (array[col] || [])[cell] || [];
}
用法
var neighbors = [].concat(
getCell(field, col - 1, cell),
getCell(field, col + 1, cell),
getCell(field, col, cell - 1),
getCell(field, col, cell + 1)
);
How it works
(field[col - 1] || [])[cell] || []
It tries to get the value of
field[col - 1]
and if the value is
undefined
,field[col - 1] || []
it returns an empty array, with the locical logical OR
||
operator. What we get is either the array offield[col - 1]
or an empty array[]
.For the next index, we use the same pattern and check if
(field[col - 1] || [])[cell]
exists and if not then we take another empty array as result
(field[col - 1] || [])[cell] || []
Now we have either a truthy value, like an object or an empty array.
This is necessary, because empty arrays are not added to an array with
Array.concat
.
您基本上有 2 个选项:
第一个选项: 不要在第一行/最后一行/列中拾取:
npcSelectShip() {
let selectCol = () => {
let colIndex = Math.floor(Math.random() * (this.npcSelectionField.length-2)) +1;
let selectCell = () => {
let cellIndex = Math.floor(Math.random() * (this.npcSelectionField[colIndex].length-2)) +1;
if (this.npcSelectionField[colIndex][cellIndex].isEmpty === false) {
selectCell();
} else {
this.npcSelectionField[colIndex][cellIndex].isEmpty = false;
this.pickDirection(this.npcSelectionField, colIndex, cellIndex);
}
}
selectCell();
}
selectCol();
}
(参见
Math.random
函数调用后的“-2”和“+1”)
Math.floor(Math.random() * (length-2)) +1;
将取
floor(0*(length-2)) +1 = 1
和
floor(1*(length-2)) +1 = length-1
第二个选项: 设定条件,不将超出范围的内容添加为邻居
pickDirection(field, col, cell) {
let neighbors = [];
if(col-1 >= 0) {
neighbors.push(field[col - 1][cell]);
}
if(col < field.length) {
neighbors.push(field[col + 1][cell]);
}
if(cell-1 >= 0) {
neighbors.push(field[col][cell -1]);
}
if(cell < field[col].length) {
neighbors.push(field[col][cell +1]);
}
let randDir = () => {
let randIndex = neighbors[Math.floor(Math.random() * neighbors.length)];
if (randIndex.isEmpty === false) {
randDir();
} else {
randIndex.isEmpty = false;
}
}
randDir();
}