Creating an image puzzle in React

Skylar S
SkyTech
Published in
4 min readJan 18, 2019

Above is an example of the kind of puzzle we’re making. Let’s divide this task into two parts: the basic functionality of swapping blocks, and displaying an image between those blocks.

Part 1: Swapping Blocks

The problem:

Let’s say you have a grid, containing blocks numbered 1–25.

Can you make it so that when a user clicks on a tile, it is selected, and when the user clicks on a second tile, it switches places with the first?

The solution:

The first thing we need to do is generate an array of elements with a key corresponding to its position in the array. For example, a block with id=10 will later display the text “10”. This is both to tell our blocks apart and so that we can test to see if the blocks are in order.

Next, we need to shuffle the blocks in the array. Here is a function I wrote to do that. There may be better options, so do some research if you’d like.

Next, we need to select the two blocks we are swapping, then swap them. We’ll break this out into two different methods.

Now, let’s write a select handler. If a square is already selected, when the user clicks on a square we’ll call our swap method with the id of the square being clicked and square that was selected. If no square is selected, we’ll select the square by saving its id to a variable.

It’s now time to write our swap function! Our swap function will copy item one, then overwrite it with item two. Item one will then go where item two used to be.

We now have everything we need to swap tiles. All we need to do is call our callback function on tile click.

We now have a functioning Tile Clicker!

Part two: Adding Images

Here is the strategy we’ll use to add images to the tiles:
Each tile will have style overflow hidden. It will display an image whose actual content is 25 time larger than the container, but with margins shifted to the appropriate distance.

A picture inside a tile div

In the example above, the image is much larger than the div it is in. The image is given an absolute position of top: -533px, which places the top of the image way above the visible portion of the container. Thus, only a tiny corner of the image is visible to the user.

For this strategy to work, the following things must be true:

  • The css width and height of the divs must divide equally into the css width and height of the picture. Here, we’re making a 5 by 5 grid, so the width and height of the square must be 1/5 the width and height of the css of the picture. That’s 200px wide and 133px high, for us.
  • The image inside each columns divs must have css left property that is the negative of whatever the starting height of the row is. For example, if I’m one square to the right of center, I must push the image that’s in me one square to the right. More precisely -200px to the left.
  • The same is true for the rows: If I’m in the second row, my contents should be shifted up one row so that the part that’s visible corresponds with the second row. That’s -133, top.

That’s all there is to it! Here’s what the math works out to for an image that is 1000px by 667 px:

Here, Math.floor(i/5) represents which row the tile is in. That number is then multiplied by -134px, which is the height of the row, to shift the picture up one row. i%5 represents the column we are in. It’s responsible for calculating that for example, the 6th tile is in the first column, or that the 7th tile is in the 2nd tile. The number of the column is then multiplied by 200.

Finally these styles are applied to the JSX elements:

That’s all we need to build a cool puzzle!

--

--