Search code examples
javascriptunit-testingtestingjestjstdd

Why does the matrix update the index for both the columns?


I am building a gameboard in JS for a battleship game and here's its current structure:

export default class Gameboard {
  constructor(size) {
    this.grid = this.#createMatrix(size);
  }

  #createMatrix(size) {
    const mat = new Array(size);
    for (let i = 0; i < size; i++) {
      // ship - for ship object if it exists, attacked - isAttacked?,
      // index - relative placement of ship tile wrt whole ship, if it exists
      mat[i] = new Array(size).fill({ ship: null, attacked: false, index: -1 });
    }
    return mat;
  }

  /**
   * @param {Ship} ship to be placed
   * @param {int} x starting x coordinate of ship placement
   * @param {int} y starting y coordinate of ship placement
   */
  placeShip(ship, x, y) {
    for (let i = 0; i < ship.length; i++) {
      
      this.grid[x][y]["ship"] = ship;
      this.grid[x][y]["index"] = i;
      console.log(this.grid[x][y]);
      y++; //move to next column for next tile placement

    }
  }
}

I can't understand why the following test to place a ship horizontally on it fails:

it("places ships", () => {
    const gameboard = new Gameboard(2);
    const ship = new Ship(2);
    gameboard.placeShip(ship, 0, 0);

    expect(gameboard.grid).toEqual([
      [
        { ship: ship, index: 0, attacked: false },
        { ship: ship, index: 1, attacked: false },
      ],
      [defaultObj, defaultObj],
    ]);
  });

Error message:

enter image description here

It appears that while looping, both columns' objects get updated but I want only one column's to be updated.


Solution

  • The problem is here:

    new Array(size).fill({ ship: null, attacked: false, index: -1 })
    

    There, you're creating one "ship" object, and you're filling the array with references to that one object.

    You can do it like this instead, to create a new ship for every entry:

    new Array(size).fill().map(() => ({ ship: null, attacked: false, index: -1 }));