2.1.0 • Published 5 years ago

klotski v2.1.0

Weekly downloads
2
License
MIT
Repository
github
Last release
5 years ago

klotski (华容道)

A fast JavaScript engine for solving klotski games.

npm version Build Status Coverage Status dependencies Status devDependencies Status Donate

cover

Installation

node.js

Install using npm:

$ npm install klotski

Browser

Using bower:

$ bower install klotski

If you are not using any module loader system then the API will then be accessible via the window.Klotski object.

CDN

The latest version is now also always available at https://unpkg.org/pkg/klotski/

<script src="https://unpkg.co/klotski/dist/klotski.min.js"></script>

Usage

Default usage

var Klotski = require('klotski');

var klotski = new Klotski();
var game = {
  blocks: [
    { "shape": [2, 2], "position": [0, 1] },
    { "shape": [2, 1], "position": [0, 0] },
    { "shape": [2, 1], "position": [0, 3] },
    { "shape": [2, 1], "position": [2, 0] },
    { "shape": [2, 1], "position": [2, 3] },
    { "shape": [1, 2], "position": [2, 1] },
    { "shape": [1, 1], "position": [3, 1] },
    { "shape": [1, 1], "position": [3, 2] },
    { "shape": [1, 1], "position": [4, 0] },
    { "shape": [1, 1], "position": [4, 3] },
  ],
  boardSize: [6, 6],
  escapePoint: [2, 4],
};

var result = klotski.solve(game);

The first block is the blocks list is always the one that tries to escape.

The shape property defines the shape of the block, for example, [1, 2] means a horizontal block has 1 row and 2 columns, [3, 1] means a vertical block that has 3 rows and 1 column.

position: [x, y] is the initial position [x, y] of the block, it uses zero-based numering.

boardSize: [rows, columns] is the size of the game board.

escapePoint: [x, y] is the destination point for block 0 to escape.

Each block's movement can also be restricted, for example { "shape": [2, 1], "position": [0, 0], directions: [0, 2] }, this will only allow the block to move up and down. The directions code is as follows:

down: 0
right: 1
up: 2
left: 3

Algorithm

Breadth-first search (BFS)

BFS is an algorithm for traversing or searching tree or graph data structures. It starts at the tree root and explores the neighbor nodes first, before moving to the next level neighbors. Basically, we start from the initial game state, try to move every block and generate the new game states, scan each new game state and see if the 2x2 block is at the desired position, if not, we will continue to try. During the try, any duplicate state should be avoided.

Zobrist hashing

There are many different ways to represent the current state of the game. We can concatenate each block's position and type to form a string, or we can use the feature of JavaScript Number datatype to optimize the storage space, see this article. The problem is it takes O(n²) time to compute the state, and it's really expensive, is there a better way?

We can use Zobrist hashing, according to Wikipedia, "Zobrist hashing is a hash function construction used in computer programs that play abstract board games, such as chess and Go, to implement transposition tables, a special kind of hash table that is indexed by a board position and used to avoid analyzing the same position more than once." Based on the current game state, if a block's position is changed, it only takes O(1) time to compute the next state, this is a huge win, and it is the key to boost the performance of the algorithm. See the getZobristHashUpdate() function in klotski.js.

Another important factor to improve the algorithm is to avoid the mirror states. For example, the following two states are mirror states:

with Zobrist hashing, we can calculate the mirror state in O(1) time, see getMirrorZobristHash() function in klotski.js.

At last, in order to use Zobrist hashing, we have to initialize the hashing table. Basically we need to generate a random number for each possible state inside a single cell of the board. A normal Klotski game has 20 cells (5 rows x 4 columns), and each cell can be empty or occupied by 5 different types of blocks. In klotski.js, we use a three-dimensional array to store the initial random numbers, see initZobristHash() function for more details.

Benchmark

The average running time is calculated by finding the minimum moves of each game 100 times.

12345
横刀立马指挥若定将拥曹营齐头并进并分三路
81 moves71 moves73 moves60 moves73 moves
65.7 ms63.2 ms66.4 ms65.4 ms46.1 ms
678910
雨声淅沥左右布兵桃花园中一路进军一路顺风
47 moves54 moves70 moves58 moves39 moves
5.3 ms71.9 ms80.6 ms74.8 ms5.0 ms
1112131415
围而不歼捷足先登插翅难飞守口如瓶 I守口如瓶 II
62 moves32 moves62 moves83 moves100 moves
4.6 ms3.1 ms146.8 ms145.8 ms151.0 ms
1617181920
双将挡路横马当关层层设防 I层层设防 II兵挡将阻
73 moves84 moves103 moves121 moves88 moves
143.6 ms138.9 ms96.6 ms122.2 ms119.7 ms
2122232425
堵塞要道瓮中之鳖层峦叠嶂水泄不通四路进兵
41 moves107 moves80 moves78 moves88 moves
35.2 ms100.1 ms31.2 ms41.5 ms34.8 ms
2627282930
入地无门勇闯五关四面楚歌前呼后拥兵临曹营
88 moves34 moves57 moves22 moves34 moves
34.8 ms3.4 ms30.2 ms1.7 ms3.0 ms
3132333536
五将逼宫前挡后阻近在咫尺小燕出巢比翼横空
36 moves42 moves99 moves107 moves28 moves
11.8 ms32.7 ms151.9 ms103.0 ms6.9 ms
3738394034
夹道藏兵屯兵东路四将连关峰回路转走投无路
78 moves73 moves40 moves140 movesno solution
34.9 ms67.6 ms6.6 ms141.3 ms-

Contribution

Anyone who would like to contribute to the project is more than welcome.

  • Fork this repo
  • Make your changes
  • Submit pull request

License

MIT License

Copyright (c) 2017 Yong Su @jeantimex

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

2.1.0

5 years ago

2.0.0

5 years ago

1.1.0

5 years ago

1.0.2

5 years ago

1.0.1

7 years ago

1.0.0

7 years ago

0.0.12

7 years ago

0.0.11

7 years ago

0.0.10

7 years ago

0.0.9

7 years ago

0.0.8

7 years ago

0.0.6

7 years ago

0.0.3

7 years ago

0.0.2

7 years ago

0.0.1

7 years ago