开发者问题收集

数组内部边界的条件

2017-08-10
55

我有一个矩阵,我有一个函数可以使用以下代码随机选择数组中的一个元素:

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?

感谢您的帮助。

2个回答

您可以使用 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 of field[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 .

Nina Scholz
2017-08-10

您基本上有 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 = 1floor(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();
}
NatNgs
2017-08-10