Home > OS >  why does array copy changes after changing real array?
why does array copy changes after changing real array?

Time:04-04

I am programming chess engine in order to see in the futere I have to change board configuration and remove changed parts A lot in short problem is this

function chessAi(){
    let copy=[...board]
    pisces.forEach(pisce=>{
    pisce.forEach(move=>{
       //play move on the board
       //reset board to original board
       board=copy
       }
    }
}

this just doesnot work and I cant figure out why,however I messed around and find that if I define copy on every move like this

function chessAi(){
    pisces.forEach(pisce=>{
    pisce.forEach(move=>{
       let copy=[...board]
       //play move on the board
       //reset board to original board
       board=copy
       }
    }
}

it works perfectly can someone explain why and how to fix that? this takes a lot of processing power and makes calculating moves much harder. thanks in advance

CodePudding user response:

In the first iteration of your first code snippet you create a clone (copy) of board array but after the first iteration and in the next iterations you are working on the same array you created on the first iteration that is why you get unexpected results.

But in your second code snippet you are creating new clone (copy) of the board array in each iteration.

A solution to your problem could be reset board variable with a clone (copy) of the copy variable:

function chessAi(){
    let copy=[...board]
    pisces.forEach(pisce=>{
    pisce.forEach(move=>{
       //play move on the board
       //reset board to original board
       board=[...copy]
       }
    }
}

CodePudding user response:

After the first iteration of pisce.forEach copy and board will reference the same array. One way, as @vcodepro mentioned, is to restore the board by cloning the copy. Another alternative is that you clone it at the start of each iteration and throw it away after the processing is done:

function chessAi(){
    let selectedConfig = null
    pisces.forEach(pisce=>{
    pisce.forEach(move=>{
       newConfig = [...board]
       //play move on the newConfig
       //if the newConfig is appropriate
       selectedConfig = newConfig
       }
    }
    return selectedConfig
}

This way you are keeping the current state of the board safe from any modification. Otherwise, if you want to use board in some other places and it has been modified here, it may cause hard to find bugs.

CodePudding user response:

The spread operator makes deep copies of data if the data is not nested.

It means when you have nested data in an array the spread operator will create a deep copy of the top most data and a shallow copy of the nested data. That's the reason it getting change when actual array changes.

Let me explain with an example :

// Original Array
let board = ['board1', 'board2',['board3','board4']];

// On copy this board data to a new variable via spread operator.
let copy = [...board];

// It looks like we get a deep copy of whole board array but in fact we don’t.
console.log(copy[0]) // 'board1'
console.log(copy[2][1]) // 'board4'

Now, if we change the array saved at index 2, copy[2][1] not only does it change the data for our variable "board" but "copy" as well. So it means board[2][1] points to the same array that copy[2][1] points to in memory.

That's the reason your second solution works as you are making deep copy of each nested array after each iteration.

  • Related