0

I am making a web application to visualise path-finding algorithms using react. I currently have Dijkstra's algorithm implemented. However, when I passed a copy of my initial grid array to my pathfinding algorithm the original array gets modified.

import React, { useState } from "react";
import Node from "./Node";
import dijkstras from "../algorithms/dijkstras";

const START_NODE_ROW = 10;
const START_NODE_COL = 15;
const FINISH_NODE_ROW = 10;
const FINISH_NODE_COL = 35;

const getGrid = () => {
  const grid = [];
  for (let row = 0; row < 20; row++) {
    const currentRow = [];
    for (let col = 0; col < 50; col++) {
      currentRow.push(createNode(col, row));
    }
    grid.push(currentRow);
  }
  return grid;
};

const createNode = (col, row) => {
  return {
    col,
    row,
    isStart: row === START_NODE_ROW && col === START_NODE_COL,
    isFinish: row === FINISH_NODE_ROW && col === FINISH_NODE_COL,
    distance: Infinity,
    isVisited: false,
    isWall: false,
    previousNode: null
  };
};

const Pathfinder = () => {
  const initialGrid = getGrid();
  const [grid, setGrid] = useState([...initialGrid]);

  const animatePath = visitedNodesInOrder => {
    for (let i = 0; i < visitedNodesInOrder.length; i++) {
      setTimeout(() => {
        const node = visitedNodesInOrder[i];
        const newGrid = grid.slice();
        const newNode = {
          ...node,
          isVisited: true
        };
        newGrid[node.row][node.col] = newNode;
        setGrid(newGrid);
      }, 100 * i);
    }
  };

  const visualizeDijkstras = () => {
    const tempGrid = [...grid];
    const startNode = tempGrid[START_NODE_ROW][START_NODE_COL];
    const finishNode = tempGrid[FINISH_NODE_ROW][FINISH_NODE_COL];
    const visitedNodesInOrder = dijkstras(tempGrid, startNode, finishNode);
    animatePath(visitedNodesInOrder);
  };

  return (
    <>
      <button onClick={() => visualizeDijkstras()}></button>
      <div className="grid">
        {grid.map((row, rowIndex) => {
          return (
            <div key={rowIndex}>
              {row.map((node, nodeIndex) => {
                const { isStart, isFinish, isVisited } = node;
                return (
                  <Node
                    key={nodeIndex}
                    isStart={isStart}
                    isFinish={isFinish}
                    isVisited={isVisited}
                  />
                );
              })}
            </div>
          );
        })}
      </div>
    </>
  );
};

export default Pathfinder;

Currently all nodes are set to visited on the first iteration of the animatePath() method because the nodes in the initial grid array have already been marked as visited by the dijkstras method. Despite me copying the initial array into the temp array and passing that to the path finding method.

1
  • 4
    You need to make copies of all nested arrays as well. tempGrid = new array, tempGrid[START_NODE_ROW] = reference to original nested array. Commented Jan 7, 2020 at 22:06

1 Answer 1

2

As stated in my comment, the issue is your copied array has nested arrays that point to their original references. So when you create a new array like this ...grid you're building your new array with references to the original sub-arrays.

The solution is to create new sub-arrays as well.

If the array is only 2 deep you can do something like this:

const tempGrid = [...grid.map.(subArray => [...subArray])];
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.