A sliding puzzle solver in pure javascript, based on this Smashing magazine article.
The idea started as just wanting to create a simple sliding puzzle gamepage where users
- could try and solve a 9x9 puzzle whose contents would be randomized everytime.
- could upload their own image,
- which would then be converted into a 9x9 puzzle grid,
- and then played at their own leisure.
- What would be nice is to create shareable links as well for the user generated puzzles
Instead I stumbled on this solver article that uses and explains the A-star algorithm (which I have so far only used in SLAM) and I thought it would be fascinating to try out. The explanation doesn't go in too deep, enough to give you a basic understandinghow the solver works. But I have to admit, the code leaves you a little lacking, and some errors.
But didn't take too long to debug. Once it was working,
- made it "more dynamic" so that the solver always takes in the latest state of the puzzle to solve
- provided a dropdonw list to choose which heurestic to use for the solver
While looking up ways to shuffle the tiles, came across this repo by @danishmughal which does the whole thing quite beautifully. So, my implementation is based on this.
My original idea was to just shuffle the 2D array, for which I had come across these two nice stack overflow responses - Knuth Shuffle in JS and Array.reduce. However, I liked Danish idea more, hence didn't get around to fully implementing these two. However, here's a code snippet:
function shuffle(array) {
let currentIndex = array.length, randomIndex;
// While there remain elements to shuffle.
while (currentIndex != 0) {
// Pick a remaining element.
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
// And swap it with the current element.
[array[currentIndex], array[randomIndex]] = [
array[randomIndex], array[currentIndex]];
}
return array;
}
// Assume this is the starting state of grid
start_arr = [[6,4,7], [8,5,0], [3,2,1]]
// First reduce to 1D array
const arr1D = start_arr.reduce((a,b) => [...a, ...b], [])
console.log(arr1D)
// Shuffle this 1D array
shuffleTiled = shuffle(arr1D)
// Now reduce shuffled array back to original shape
shuffleTile2D = shuffleTiled.reduce((acc,i) => {
if(acc[acc.length-1].length>=3) {
acc.push([])
}
acc[acc.length-1].push(i)
return acc
}, [[]])
console.log(shuffleTile2D)
- ### Solver
- ### User images
- Deploy
- Add animation when solution/goal reached