1

I'm creating a dungeon crawler game using React.js and I was initializing the board using Array.fill(0). but when I set an element inside the 2d array it sets the entire Array (column) to 'player' instead of a singular element. I have another createBoard() function, commented out, that works correctly. So why does this happen and how can I use Array.fill correctly?

Here is my Board component:

import React, {Component} from 'react';
import Cell from './Cell';

class Board extends Component {
  constructor(props) {
    super(props);
    const dim = 10;
    let board = this.createBoard(dim, dim);
    this.state = {
      board: board,
    };
  }

  createBoard = (row, col) => {
    return Array(row).fill(Array(col).fill(0));
  }

  // createBoard = (rows, cols) => {
  //   let board = [];
  //   for (let i = 0; i < rows; i++) {
  //     let row = [];
  //     for (let j = 0; j < cols; j++) {
  //       row.push(0);
  //     }
  //     board.push(row);
  //   }
  //   console.log(board);
  //   return board;
  // }

  movePlayer = () => {

  }

  componentDidMount() {
    this.setPiece(this.props.player);
  }

  setPiece = (loc) => {
    let brd = this.state.board;
    const row = loc[0];
    const col = loc[1];
    console.log('row: '+row+' col: '+col+' ==='+brd[row][col]);
    brd[row][col] = 'player';
    console.log('setPiece: ',brd);
    this.setState({board: brd});
  }

  renderCell = (cell) => {
    switch(cell) {
      case 0:
        return 'floor';
      case 1:
        return 'wall';
      case 'player':
        return 'player';
      default:
        return 'floor';
    }
  }

  render() {
    return (
      <div className='board'>
      {this.state.board.map((row, i) => {
        return row.map((cell, j) => {
          return (
            <Cell
              key={[i, j]}
              loc={[i, j]}
              type={this.renderCell(cell)}
            />
          );
        })
      })}
      </div>
    );
  }
}

export default Board;
ChrisR
  • 607
  • 6
  • 16
  • Because your first fill is simply filling every column position with references to the same array. – pvg Jun 25 '17 at 19:09

2 Answers2

3

You are using Array#fill correctly. Array#fill populates the array cells with the same value:

  1. The sub array is created - Array(col).fill(0)
  2. All row arrays are filled with the array reference - Array(row).fill(Array(col).fill(0))

To prevent that, you can use other methods of array creation, that create instead of clone the value. For example Array#from:

const row = 10;
const col = 5;
const result = Array.from({ length: row }, () => new Array(col).fill(0));

result[0][2] = 5

console.log(result);
Ori Drori
  • 183,571
  • 29
  • 224
  • 209
1

You can fill 2D array with a help of Array.fill in a such way:

let arr = Array(5).fill(0).map(x => Array(5).fill(0))
  • This one looks great! It makes perfect sense to me! – ChrisR Jun 25 '17 at 20:13
  • 1
    This doesn’t answer the question what the difference between the working and the non-working approach is and why the non-working one isn’t working. The issue is that `.fill(new Array(`…`))` will fill an array with the _same array reference_. – Sebastian Simon Jan 21 '18 at 19:13