0

I'm attempting to update the "position" key of each object in the shipArray variable. The goal is to have each position array contain unique values and a length == shipLength of that object. However, this code results in duplicate values being generated on some runs. Any help solving this would be greatly appreciated.

// Array of objects
const shipArray = [
  {
    name: "first ship",
    shipLength: 5,
    position: []
  },
  {
    name: "second ship",
    shipLength: 4,
    position: []
  },
  {
    name: "third ship",
    shipLength: 3,
    position: []
  },
  {
    name: "fourth ship",
    shipLength: 3,
    position: []
  },
  {
    name: "fifth ship",
    shipLength: 2,
    position: []
  },
];

// Generates an array of numbers satisfying the conditions therein.
const createShip = (length) => {
  const directionArray = ["horizontal", "vertical"];
  let direction = directionArray[Math.floor(Math.random() * 2)];
  const num = Math.floor(Math.random() * 100);
  const posArray = []
  for (let i = 0; i < length; i++) {
    if (direction == "vertical" && ((num + (length * 10)) <= 99)) {
      posArray.push(num + (i * 10));
    } else if (direction == "vertical" && ((num + (length * 10)) >= 99)) {
      const newNum = (num - 40);
      posArray.push(newNum + (i * 10));
    } else if (direction == "horizontal" && ((num % 10) <= length)) {
      posArray.push(num + i);
    } else if (direction == "horizontal" && ((num % 10) >= length)) {
      const newNum = (num - (length - 1));
      posArray.push(newNum + i);
    }
  }
  return posArray;
}

// Should theoretically prevent duplicate positions 
const noShipCollision = (array, position) => {
  for (let i = 0; i < array.length; i++) {
    let vessel = array[i];
    for (let j = 0; j < position.length; j++) {
      if (vessel.position.indexOf(position[j]) >= 0) {
        return false;
      }
    }
  }
  return true;
}

// Returns an updated array of objects
const populateBoard = (shipObjectsArray) => {
  // Iterates over array of ship objects
  let ship;

  for (let i = 0; i < shipObjectsArray.length; i++) {
    do {
      ship = createShip(shipObjectsArray[i].shipLength);
    } while (!noShipCollision(shipObjectsArray, shipObjectsArray[i].position))
    shipObjectsArray[i].position = ship;
  }
  return shipObjectsArray;
}
console.log(populateBoard(shipArray));
Josiah
  • 207
  • 3
  • 13
Genetic1989
  • 614
  • 1
  • 6
  • 19
  • 1
    Put all the positions in an array. Shuffle the array. Then assign the positions to the ships. – Barmar Jan 30 '20 at 21:47
  • Sounds like a [set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) data structure is what you need, – eMontielG Jan 30 '20 at 22:13
  • 1
    Found it: you need `!noShipCollision(shipObjectsArray, ship)` (you are passing `shipObjectsArray[i].position` as the second parameter, which at that point is still empty, so collisions are never detected) –  Jan 30 '20 at 22:33
  • @ChrisG your suggestion worked like a charm! Thanks a lot, man! – Genetic1989 Jan 30 '20 at 22:50

0 Answers0