1.0.3 • Published 2 months ago

unblock-me-solver v1.0.3

Weekly downloads
-
License
ISC
Repository
github
Last release
2 months ago

Unblock me solver

This is a solver for the classic game Unblock me

Interface

The package exposes a solve function which takes in a board state and returns the optimal solution as an array of Move objects.

Object structure:

Block: { id: number, x: number, y: number, width: number, height: number }

Move: { blockId: number, amount: number, dir: 'x' | 'y' }

Solver interface

Function: solve

ParamTypeDescription
initialBlocksBlock[]The configuration of the blocks on the board
maxHeightnumber default 6The height of the board
maxWidthnumber default 6The width of the board
maxWidthboolean default falseA flag to determine whether blocks can only move in the direction of their larger size or in both directions
goalYnumber default 2The row where the goal is
ReturnsMove[]A list the moves for the optimal solution

Implementation

The solver is implemented using a Breadth-first-search (BFS) algorithm. For each board state, all legal moves are calculated and added to the search queue. The queue is expanded in a FIFO-manner, hence BFS. Duplicate states are detected by comparing the stringified representations of each board. The search stops when the goal state is reached. The list of moves needed for each state is stored alongside the state in the queue. This allows us to trace back the optimal solution once the goal state is reached.

Usage

For instance, given the following board state:

..22.3
.....3
1145..
..45..
6677..
....88

The following code will return the optimal solution:

import { solve } from 'unblock-me-solver';

const blocks = [
    { id: 1, x: 0, y: 2, width: 2, height: 1 },
    { id: 2, x: 2, y: 0, width: 2, height: 1 },
    { id: 3, x: 5, y: 0, width: 1, height: 2 },
    { id: 4, x: 2, y: 2, width: 1, height: 2 },
    { id: 5, x: 3, y: 2, width: 1, height: 2 },
    { id: 6, x: 0, y: 4, width: 2, height: 1 },
    { id: 7, x: 2, y: 4, width: 2, height: 1 },
    { id: 8, x: 4, y: 5, width: 2, height: 1 },
];

const solution = solve(blocks);
console.log(solution);
Output:
[
  { id: 2, amount: -2, dir: 'x' },
  { id: 4, amount: -2, dir: 'y' },
  { id: 5, amount: -2, dir: 'y' },
  { id: 1, amount: 4, dir: 'x' }
]

Notes

In the original game, the board is always 6 x 6. However, the solver can handle boards of any size. The default board size is 6 x 6, but this can be overridden by passing the maxHeight and maxWidth parameters to the solve function. Additionally, blocks can only move in the direction of their larger size by default. This can be overridden by passing the bidirectional parameter to the solve function. The goal row is 2 by default, but this can be overridden by passing the goalY parameter to the solve function.

acornacorn-jsxacorn-walkajvansi-escapesansi-regexansi-stylesanymatchargargparsearray-unionbabel-jestbabel-plugin-istanbulbabel-plugin-jest-hoistbabel-preset-current-node-syntaxbabel-preset-jestbalanced-matchbig-integerbplist-parserbrace-expansionbracesbrowserslistbs-loggerbserbuffer-frombundle-namecallsitescamelcasecaniuse-litechalkchar-regexci-infocjs-module-lexercliuicocollect-v8-coveragecolor-convertcolor-nameconcat-mapconvert-source-mapcreate-jestcreate-requirecross-spawndebugdedentdeep-isdeepmergedefault-browserdefault-browser-iddefine-lazy-propdetect-newlinediffdiff-sequencesdir-globdoctrineelectron-to-chromiumemitteryemoji-regexerror-exescaladeescape-string-regexpeslint-rule-composereslint-scopeeslint-visitor-keysespreeesprimaesqueryesrecurseestraverseesutilsexecaexitexpectfast-deep-equalfast-difffast-globfast-json-stable-stringifyfast-levenshteinfastqfb-watchmanfile-entry-cachefill-rangefind-upflat-cacheflattedfs.realpathfunction-bindgensyncget-caller-fileget-package-typeget-streamglobglob-parentglobalsglobbygraceful-fsgraphemerhas-flaghasownhtml-escaperhuman-signalsignoreimport-freshimport-localimurmurhashinflightinheritsis-arrayishis-core-moduleis-dockeris-extglobis-fullwidth-code-pointis-generator-fnis-globis-inside-containeris-numberis-path-insideis-streamis-wslisexeistanbul-lib-coverageistanbul-lib-instrumentistanbul-lib-reportistanbul-lib-source-mapsistanbul-reportsjest-changed-filesjest-circusjest-clijest-configjest-diffjest-docblockjest-eachjest-environment-nodejest-get-typejest-haste-mapjest-leak-detectorjest-matcher-utilsjest-message-utiljest-mockjest-pnp-resolverjest-regex-utiljest-resolvejest-resolve-dependenciesjest-runnerjest-runtimejest-snapshotjest-utiljest-validatejest-watcherjest-workerjs-tokensjs-yamljsescjson-bufferjson-parse-even-better-errorsjson-schema-traversejson-stable-stringify-without-jsonifyjson5keyvkleurlevenlevnlines-and-columnslocate-pathlodash.memoizelodash.mergelru-cachemake-dirmake-errormakeerrormerge-streammerge2micromatchmimic-fnminimatchmsnatural-comparenode-int64node-releasesnormalize-pathnpm-run-pathonceonetimeopenoptionatorp-limitp-locatep-tryparent-moduleparse-jsonpath-existspath-is-absolutepath-keypath-parsepath-typepicocolorspicomatchpiratespkg-dirprelude-lsprettierprettier-linter-helperspretty-formatpromptspunycodepure-randqueue-microtaskreact-isrequire-directoryresolveresolve-cwdresolve-fromresolve.exportsreusifyrimrafrun-applescriptrun-parallelsemvershebang-commandshebang-regexsignal-exitsisteransislashsource-mapsource-map-supportsprintf-jsstack-utilsstring-lengthstring-widthstrip-ansistrip-bomstrip-final-newlinestrip-json-commentssupports-colorsupports-preserve-symlinks-flagsynckittest-excludetext-tabletitleizetmplto-fast-propertiesto-regex-rangets-api-utilstslibtype-checktype-detecttype-festundici-typesuntildifyupdate-browserslist-dburi-jsv8-compile-cache-libv8-to-istanbulwalkerwhichwrap-ansiwrappywrite-file-atomicy18nyallistyargsyargs-parserynyocto-queue
1.0.3

2 months ago

1.0.2

2 months ago

1.0.1

2 months ago

1.0.0

2 months ago