1

I've made a multidimensional array with Array constructor and Array.fill method. I cannot figure out where the problem is, but this code doesn't work as I want.

function loadChunk(){
    for(var x = 0; x< 3; x++){
        for(var y=  0; y < 3; y++){
            console.log(x+","+y);
            console.log((world[x][y]).loaded);
            if(!(world[x][y]).loaded){
             world[x][y].loaded=true;
            }
        }
    }
}

function createWorld(w, d){
    var worldz = new Array(d * 2 + 1);
    var world = new Array(w * 2 + 1);
    world.fill(worldz);
    for(var x = 0; x< w * 2+ 1; x++){
        for(var z = 0; z < d * 2 + 1; z++){
            world[x][z]= { loaded: false };
        }
    }
    return world;
}


var world = createWorld(1, 1);
Start();
function Start(){
    loadChunk();
}

You can see what is happening with console. With my view, no true should be written on console.

The problem is, if I edit world[0][n],then world[1 or more][n] changes too.

Chris Barr
  • 29,851
  • 23
  • 95
  • 135
ProJs er
  • 45
  • 6
  • Also, you're filling an array with the same object. It's normal that all the values change. I believe. – Ismael Miguel Jan 29 '19 at 15:24
  • @IsmaelMiguel Then what should I do to make sized multidimensional array? – ProJs er Jan 29 '19 at 15:25
  • Possible duplicate of [Modifying a copy of a JavaScript object is causing the original object to change](https://stackoverflow.com/questions/29050004/modifying-a-copy-of-a-javascript-object-is-causing-the-original-object-to-change) – Heretic Monkey Jan 29 '19 at 15:26
  • You might also be interested in [Why does changing an Array in JavaScript affect copies of the array?](https://stackoverflow.com/q/6612385/215552). – Heretic Monkey Jan 29 '19 at 15:27
  • @HereticMonkey I used Array.slice method on worldz array, but it didnt work either. – ProJs er Jan 29 '19 at 15:30
  • You can't use `fill` in this instance, since it fills the `world` array with *references* to the `worldz` array. Instead, after `for(var x = 0; x< w * 2+ 1; x++){` add a `world[x] = new Array(d * 2 + 1);` before the inner loop. – Heretic Monkey Jan 29 '19 at 15:34
  • @HereticMonkey Thanks! It works – ProJs er Jan 29 '19 at 15:38
  • @ProJS er Welcome to stackoverflow. If any answer helped you with your problem, you should tag it as the the right answer. – Michael Besteck Jan 31 '19 at 16:13

3 Answers3

0
function loadChunk() {
    for (var x = 0; x < 3; x++) {
        for (var y = 0; y < 3; y++) {
            console.log(x + "," + y, (world[x][y]).loaded);
            if (!(world[x][y]).loaded) {
                world[x][y].loaded = true;
            }
        }
    }
}

function createWorld(w, d) {
    var world = [];
    for (var x = 0; x < w * 2 + 1; x++) {
        world[x] = [];
        for (var z = 0; z < d * 2 + 1; z++) {
            world[x][z] = {loaded: false};
        }
    }
    return world;
}


var world = createWorld(1, 1);
Start();
function Start() {
    loadChunk();
}

The problem that you expirience is that you fill "rows" of world with the same array, so world[0] === world[1] && world[1] === world[2] because array variable worldz is holding a reference

The best way to learn your problem is doing next thing:

function createWorld(w, d){
    var worldz = new Array(d * 2 + 1);
    var world = new Array(w * 2 + 1);
    world.fill(worldz);
    for(var x = 0; x< w * 2+ 1; x++){
        for(var z = 0; z < d * 2 + 1; z++){
            world[x][z]= { loaded: false };
            debugger;
        }
    }
    return world;
}

And inspecting in chrome debugger what happens with world variable on a first step

Gena Moroz
  • 929
  • 5
  • 9
0

Replace your createWorld function with this:

function createWorld(w, d){
   
    var world = new Array(w * 2 + 1);
  
    for(var x = 0; x< w * 2+ 1; x++){
      
       // each item of the array requires a new instance
       // you should not use fill method in this situation
       
        world[x]=new Array(d * 2 + 1);
      
        for(var z = 0; z < d * 2 + 1; z++){
            world[x][z]= { loaded: false };
        }
    }
    return world;
}
behzad besharati
  • 5,873
  • 3
  • 18
  • 22
0

The reason why a change of world[0][0] also changes world[1][0] and world[2][0] (same for other indecees of worldz) is that world.fill(worldz) makes all elements of world the same identical object (Array) worldz. To avoid this every element of world should be a new Array like eg:

for(n=0,max=world.length;n<max;n++) {world[n] = new Array(d * 2 + 1);}
Michael Besteck
  • 2,415
  • 18
  • 10