Skip to content

Instantly share code, notes, and snippets.

@wlib
Created April 19, 2021 18:43
Show Gist options
  • Save wlib/06b59a8f7ababe9cb006ebdbe1e38991 to your computer and use it in GitHub Desktop.
Save wlib/06b59a8f7ababe9cb006ebdbe1e38991 to your computer and use it in GitHub Desktop.
Play a 15 puzzle (or any other number) in the browser's devtools js console.
const { pipe } = await import("https://unpkg.com/[email protected]/src/util/index.mjs")
const { listen, map, filter, forEach, tap } = await import("https://unpkg.com/[email protected]/src/util/iterable/async.mjs")
const makePuzzle = (n = 4) => {
const solvedPuzzle =
[...Array(n)]
.map((_, rowI) =>
[...Array(n)].map((_, colI) => rowI * n + colI + 1)
)
solvedPuzzle[n - 1][n - 1] = null
return [...Array(100)]
.map(() =>
["up", "down", "left", "right"][Math.floor(Math.random() * 4)]
)
.reduce((puzzle, direction) => move(puzzle, direction), solvedPuzzle)
}
const move = (puzzle, direction) => {
const result = puzzle.map(row => [...row])
const emptyRow = puzzle.findIndex(row => row.includes(null))
const emptyCol = puzzle[emptyRow].indexOf(null)
const [fromRow, fromCol] =
({
up: [emptyRow + 1, emptyCol ],
down: [emptyRow - 1, emptyCol ],
left: [emptyRow , emptyCol + 1],
right: [emptyRow , emptyCol - 1]
})[direction]
if (puzzle[fromRow]?.[fromCol]) {
result[emptyRow][emptyCol] = puzzle[fromRow][fromCol]
result[fromRow][fromCol] = null
}
return result
}
const display = puzzle => {
console.clear()
if (puzzle.flat().slice(0, -1).every((n, i) => n == i + 1)) {
const name = puzzle.flat().slice(0, -1).length
console.log(`You solved the "${name} puzzle" in ${moves} moves!`)
return
}
const maxWidth = Math.max(
...puzzle.flat()
.map(n => (n || "").toString().length)
)
const table = puzzle
.map(row =>
row
.map(n =>
(n || "").toString()
.padStart(maxWidth + 1)
.padEnd(maxWidth + 2)
)
.join("")
)
.map(row => "\n" + row + "\n")
.join("")
console.log(table)
}
let currentPuzzle = makePuzzle(
parseInt(prompt("Choose your difficulty level", 4))
)
let moves = 0
display(currentPuzzle)
pipe(
listen(document, "keydown"),
map(({ key }) =>
({
ArrowUp: "up",
ArrowDown: "down",
ArrowLeft: "left",
ArrowRight: "right"
})[key]
),
filter(direction => direction != undefined),
forEach(direction => {
currentPuzzle = move(currentPuzzle, direction)
moves++
display(currentPuzzle)
})
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment