Last active
April 4, 2018 08:30
-
-
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/
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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