1

For a tic tac toe game, I'm writing a function that is supposed to find the best next move. So far I pass on the current state of the game and will then recurse through all possible moves.

var fieldModel = [
  ["x", "", ""],
  ["", "", ""],
  ["", "", "x"]
];

function aiMove() {
  for (var i = 0; i < fieldModel.length; i++) {
    for (var j = 0; j < fieldModel[i].length; j++) {
      if (fieldModel[i][j] === "") {
        function findBestMove(i, j) {
          var simModel = fieldModel.slice();
          simModel[i][j] = "o";
          console.log("simulation", simModel);
        }

        findBestMove(i, j);
      } 
    }
  }
}

aiMove();

The problem is that, as the output shows, each log shows the state of the array after all iterations have run. So obviously simModel is not as local as I want it to be.

How can I achieve that?

Jost
  • 199
  • 1
  • 3
  • 16

1 Answers1

3

When you do .slice on the multidimensional array, you clone only the root array, but the inner arrays still point to their original references.

For instance:

[ // < This is cloned
   [1, 2, 3, 4], // <=These are not
   [1, 2, 3, 4]  // </
] 

Also, as Jan pointed out, because the browser console will display the updated array in the console log when it's mutated. If you want to avoid that you can simply console.log(JSON.stringify(simModel)) so that you will output a string.

If you really want to have a new clone of the multidimentional array, you need to map and slice each element:

var fieldModel = [
  ["x", "", ""],
  ["", "", ""],
  ["", "", "x"]
];

function aiMove() {
  for (var i = 0; i < fieldModel.length; i++) {
    for (var j = 0; j < fieldModel[i].length; j++) {
      if (fieldModel[i][j] === "") {
        function findBestMove(i, j) {
          var simModel = fieldModel.slice().map(function (c) {
             return c.slice();
          })
          simModel[i][j] = "o";
          console.log("simulation", simModel);
        }

        findBestMove(i, j);
      } 
    }
  }
}

aiMove();
Ionică Bizău
  • 109,027
  • 88
  • 289
  • 474
  • That's correct. And because devtools are smart, they update the array in the console log when it's mutated. If you only care about the logs, you could also work around this by logging the array as a serialized string: `console.log('simulation', JSON.stringify(simModel))`. – Jan Jan 28 '18 at 17:24