Search code examples
javascriptconstructortowers-of-hanoi

getting two towers updated at the same time every time I make a move Towers of Hanoi js


I am trying to write a very simple implementation of the Towers of Hanoi puzzle to practice what I have just learned about js constructors and prototypes. I am currently having problems with what I have written so far because every time I move a 'disc' from tower[0] to let's say tower[1], my tower[2] also gets updated with the same disc. Also, when I try to make an invalid move, I still get the disc I tried to move, taken away from its tower. I have checked out my logic and I can't see anything wrong with it (I could be just biased at this point too). I am wondering if it is a problem with my constructor function or any of my methods?

Here my code :

function TowersOfHanoi(numberOfTowers){
   let towersQuant = numberOfTowers || 3 , towers;
   towers = Array(towersQuant).fill([]); 
   towers[0] =  Array(towersQuant).fill(towersQuant).map((discNumber, idx) => discNumber - idx);
   this.towers = towers;
}

TowersOfHanoi.prototype.displayTowers = function(){
    return this.towers; 
}


TowersOfHanoi.prototype.moveDisc = function(fromTower,toTower){
    let disc = this.towers[fromTower].pop();
    if(this.isValidMove(disc,toTower)){
       this.towers[toTower].push(disc); 
       return 'disc moved!'
    } else {
        return 'disc couldn\'t be moved.'
    }
}

TowersOfHanoi.prototype.isValidMove = function(disc,toTower){
    if(this.towers[toTower][toTower.length-1] > disc || this.towers[toTower].length === 0){
        return true; 
    }else {
        return false;  
    }
}

this is what I am testing :

let game2 = new TowersOfHanoi();
console.log(game2.displayTowers());  
console.log(game2.moveDisc(0,1));  
console.log(game2.displayTowers());  
console.log(game2.moveDisc(0, 2));
console.log(game2.displayTowers()); 

and my output :

[ [ 3, 2, 1 ], [], [] ]
disc moved!
[ [ 3, 2 ], [ 1 ], [ 1 ] ]
disc couldn't be moved.
[ [ 3 ], [ 1 ],[ 1 ] ]

I appreciate any guidance. I am not necessarily looking for code. just to understand. Thanks


Solution

  • This quote from the Array fill() documentation tells you the problem:

    When the fill method gets passed an object, it will copy the reference and fill the array with references to that object.

       towers = Array(towersQuant).fill([]); 
    

    Arrays are objects. So what you've done is copy a reference of the first Array to each of the other arrays. The whole thing is compounded when you iterate these references to modify them.

    Update Something like this will work:

    function TowersOfHanoi(numberOfTowers){
       let towersQuant = numberOfTowers || 3 , towers = [];
       for(let i=1; i < towersQuant; i++){
         towers.push([]);
         towers[0].push(i);
       }
      towers[0].reverse();
      this.towers = towers;
    }