0

I’m building a number puzzle game with React hooks.

The idea is pretty simple. When you click next to box number 16 I want to switch the current box been clicked with the current empty box index (box 16).

Note: (I haven’t added the css or logic to hide the “empty” box).

  • I've been adding functions that add properties to each of the value in the initial array:

0: {column: 0, row: 0, box: 1}

  • I've also added logic that checks if the box that is been clicked is next to box number 16 (see distanceBetween in codeSandbox example below).

Question

  • I want to completely switch the properties (row, column, number...) of box number 16 (empty box) and box that is been clicked.

I made a codeSandbox link to show what it would look like: CodeSandbox

GameWrapper.js

import React, { useEffect, useState } from "react";
import { shuffleArray, addBoxProperties, distanceBetween } from "../lib/utils";
import Box from "./Box";
import WrapperDiv from "../elements/WrapperDiv";

const boxesArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];

export const shuffledArray = shuffleArray(boxesArray);

const GameWrapper = () => {
  const [boxes, setBoxes] = useState([]);

  useEffect(() => {
    setBoxes(generateBox(shuffledArray));
  }, []);

  const generateBox = (boxArr) => {
    const tempBox = [];

    boxArr.forEach((box, index) => {
      tempBox[index] = {
        ...addBoxProperties(index),
        box,
      };
    });

    return tempBox;
  };

  const boxClick = (box) => {
    const emptyBox = boxes.find((empty) => empty.box === 16);
    const emptyBoxIndex = boxes.indexOf(emptyBox);
    const boxIndex = boxes.findIndex((index) => index.box === box.box);

    const distance = distanceBetween(box, emptyBox);
    if (distance.neighbours) {
      swap(boxIndex, emptyBoxIndex);
    }
  };

  const swap = (clickedBoxIndex, emptyBoxIndex) => {
    let tempArr = [...boxes];
    tempArr[emptyBoxIndex] = boxes[clickedBoxIndex];
    tempArr[clickedBoxIndex] = 0;

    setBoxes(() => [...tempArr]);
  };

  console.log("boxes", boxes);
  return (
    <>
      <WrapperDiv>
        {boxes.map((box, index) => {
          return <Box {...box} onClick={boxClick} key={index} />;
        })}
      </WrapperDiv>
    </>
  );
};

export default GameWrapper;

Please ask if i need to clarify anything further or if you think that I've approaching this the right way!

Thanks beforehand, Erik

1 Answer 1

1

Your swap method is wrong. Try something like this:

  const swap = (clickedBoxIndex, emptyBoxIndex) => {
    let tempArr = [...boxes];
    const tempBox = tempArr[emptyBoxIndex] // Keep a pointer since the next line will overwrite this box
    tempArr[emptyBoxIndex] = boxes[clickedBoxIndex];
    tempArr[clickedBoxIndex] = tempBox;

    setBoxes(tempArr); // Why were you passing a method here?
  };

Also your logic to figure out whether the boxes are neighbors doesn't seem to work properly, but I guess that wasn't part of the question :)

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.