Skip to content

Instantly share code, notes, and snippets.

@zarcode
Last active April 4, 2018 08:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zarcode/8e580dd242c9ee7291e9098fd376c41e to your computer and use it in GitHub Desktop.
Save zarcode/8e580dd242c9ee7291e9098fd376c41e to your computer and use it in GitHub Desktop.
Warnsdorff’s algorithm for Knight’s tour problem in JavaScript/ES6 https://www.geeksforgeeks.org/warnsdorffs-algorithm-knights-tour-problem/
// ES6 program to for Knight's tour problem using
// Warnsdorff's algorithm
const N = 8;
let gx;
let gy;
const a = [];
function print(a) {
for (let i = 0; i < N; i += 1) {
let s = '';
for (let j = 0; j < N; j += 1) {
const space = a[j*N+i] > 9?" ":" "
s = s + space + a[j*N+i];
}
console.log(`${s}\n`);
}
}
// Move pattern on basis of the change of
// x coordinates and y coordinates respectively
const cx = [1, 1, 2, 2, -1, -1, -2, -2];
const cy = [2, -2, 1, -1, 2, -2, 1, -1];
// function restricts the knight to remain within
// the 8x8 chessboard
function limits(x, y) {
return ((x >= 0 && y >= 0) && (x < N && y < N));
}
/* Checks whether a square is valid and empty or not */
function isempty(ar, x, y) {
return (limits(x, y)) && (ar[(y * N) + x] < 0);
}
/* Returns the number of empty squares adjacent
to (x, y) */
function getDegree(ar, x, y) {
let count = 0;
for (let i = 0; i < N; i += 1) {
if (isempty(ar, (x + cx[i]), (y + cy[i]))) {
count += 1;
}
}
return count;
}
// Picks next point using Warnsdorff's heuristic.
// Returns false if it is not possible to pick
// next point.
function nextMove() {
let minDegIdx = -1;
let c;
let minDeg = (N + 1);
let nx;
let ny;
// Try all N adjacent of (*x, *y) starting
// from a random adjacent. Find the adjacent
// with minimum degree.
const start = Math.floor(Math.random() * (N + 1));
for (let count = 0; count < N; count += 1) {
const i = (start + count) % N;
nx = gx + cx[i];
ny = gy + cy[i];
c = getDegree(a, nx, ny);
if ((isempty(a, nx, ny)) && c < minDeg) {
minDegIdx = i;
minDeg = c;
}
}
// IF we could not find a next cell
if (minDegIdx === -1) {
return false;
}
// Store coordinates of next point
nx = gx + cx[minDegIdx];
ny = gy + cy[minDegIdx];
// Mark next move
a[(ny * N) + nx] = a[((gy) * N) + (gx)] + 1;
// Update next point
gx = nx;
gy = ny;
return true;
}
/* checks its neighbouring sqaures */
/* If the knight ends on a square that is one
knight's move from the beginning square,
then tour is closed */
function neighbour(x, y, xx, yy) {
for (let i = 0; i < N; i += 1) {
if (((x + cx[i]) === xx) && ((y + cy[i]) === yy)) {
return true;
}
}
return false;
}
/* Generates the legal moves using warnsdorff's
heuristics. Returns false if not possible */
function findClosedTour() {
// Filling up the chessboard matrix with -1's
for (let i = 0; i < N * N; i += 1) {
a[i] = -1;
}
// Randome initial position
const sx = Math.floor(Math.random() * (N + 1));
const sy = Math.floor(Math.random() * (N + 1));
// Current points are same as initial points
gy = sy;
gx = sx;
a[(gy * N) + gx] = 1; // Mark first move.
// Keep picking next points using
// Warnsdorff's heuristic
for (let i = 0; i < (N * N) - 1; i += 1) {
if (nextMove() === false) {
return false;
}
}
// Check if tour is closed (Can end
// at starting point)
if (!neighbour(gx, gy, sx, sy)) {
return false;
}
print(a);
return true;
}
getSolution = () => {
// While we don't get a solution
while (!findClosedTour()) {
}
};
getSolution();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment