简体   繁体   中英

Weird Behaviour when nesting 2D arrays in a 3D array

Currently I'm working on a Minimax algorithm for four-in-a-row in javascript. I have decided to store possible moves in a array, continuing to nest arrays within arrays for every branch.

However, when I attempt to edit a certain value in an array, it edits all other values within the same column.

Code:

var BOARD = [
    [0, 0, 0],
    [0, 0, 0],
    [0, 0, 0]
    ];

// Put 3 x 2D Arrays into one 3D Array
var NODE_TREE = [BOARD, BOARD, BOARD];
NODE_TREE[1][2][0] = 2;
console.log(NODE_TREE);

Chrome V8 interpreter output:

[ [ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 2, 0, 0 ] ],
  [ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 2, 0, 0 ] ],
  [ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 2, 0, 0 ] ] ]

What should happen but dosen't:

[ [ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 0, 0, 0 ] ],
  [ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 2, 0, 0 ] ],
  [ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 0, 0, 0 ] ] ]

Javascript seems to ignore the First dimension index number. This issue only happens when I use an existing array nested within an array. If I were to make a 3D array from scratch, this bug does not happen.

When you put BOARD 3 times in to the array, you are not "copying" the items in to the new array, you are actually just creating 3 references to the original BOARD array.

Therefore any change made to any one of those references will be reflected in all instances of BOARD .

If you want to create 3 distinct arrays in your 3d array you will need to clone or copy the arrays. You can do this by mapping on the outer array and copy the contents with Array.prototype.slice();

 var BOARD = [ [0, 0, 0], [0, 0, 0], [0, 0, 0] ]; // function to map and copy arrays with .slice() function sliceArrays (outerArray){ return outerArray.map((arr)=>{ return arr.slice() }); } var NODE_TREE = [sliceArrays(BOARD), sliceArrays(BOARD), sliceArrays(BOARD)]; NODE_TREE[1][2][0] = 2; console.log(NODE_TREE); //[ [ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 0, 0, 0 ] ], // [ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 2, 0, 0 ] ], // [ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 0, 0, 0 ] ] ] 

For a lazy initalization, you could use a parsed JSON string.

This generates an independent object without references to the original object.

 var BOARD = [ [0, 0, 0], [0, 0, 0], [0, 0, 0] ], JSON_BOARD = JSON.stringify(BOARD), NODE_TREE = [JSON.parse(JSON_BOARD), JSON.parse(JSON_BOARD), JSON.parse(JSON_BOARD)]; NODE_TREE[1][2][0] = 2; console.log(NODE_TREE); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM