Skip to content

Instantly share code, notes, and snippets.

@kubadlo
Created January 9, 2016 16:55
Show Gist options
  • Save kubadlo/b1604b62731e764c4841 to your computer and use it in GitHub Desktop.
Save kubadlo/b1604b62731e764c4841 to your computer and use it in GitHub Desktop.
Knigh's tour solution.
package main;
import java.awt.Point;
public class Chessboard {
private final int KNIGHT_MOVES_COUNT = 8;
private final int[][] KNIGHT_MOVES = {
{1,-2},
{2,-1},
{2,1},
{1,2},
{-1,2},
{-2,1},
{-2,-1},
{-1,-2}
};
private int boardSize;
private int[][] chessBoard;
private Point lastPosition;
public Chessboard(int size) {
boardSize = size;
chessBoard = new int[boardSize][boardSize];
}
/**
* Solve chessboard with greedy algorithm.
* @param row Start row position.
* @param col Start columnt position.
* @return True if puzzle was solved. Otherwise false.
*/
public boolean solvePuzzle(int row, int col) {
int currentRow = row;
int currentCol = col;
chessBoard[row][col] = 1;
for (int move = 2; move <= (boardSize * boardSize); move++) {
boolean[] possibleMoves = new boolean[KNIGHT_MOVES_COUNT];
int[] countedMoves = new int[this.KNIGHT_MOVES_COUNT];
// Compute available moves from current position
for (int i = 0; i < KNIGHT_MOVES_COUNT; i++) {
int nextRow = currentRow + KNIGHT_MOVES[i][0];
int nextCol = currentCol + KNIGHT_MOVES[i][1];
if (!isMovePossible(nextRow, nextCol) || isVisited(nextRow, nextCol)) {
continue;
}
possibleMoves[i] = true;
countedMoves[i] = countMoves(nextRow, nextCol);
}
// Get index of move that have minimum of next possible moves
int minimum = KNIGHT_MOVES_COUNT + 1;
int index = -1;
for (int i = 0; i < KNIGHT_MOVES_COUNT; i++) {
if (possibleMoves[i]) {
if (index < 0 || minimum == 0 || countedMoves[i] < minimum && countedMoves[i] != 0) {
minimum = countedMoves[i];
index = i;
}
}
}
// If this index is -1 - solution was not found . Set last visited position and return false.
if (index < 0) {
lastPosition = new Point(currentCol, currentRow);
return false;
}
// Set new position for next iteration
currentRow = currentRow + KNIGHT_MOVES[index][0];
currentCol = currentCol + KNIGHT_MOVES[index][1];
chessBoard[currentRow][currentCol] = move;
}
// Solution was found. Set last visited position and return true.
lastPosition = new Point(currentCol, currentRow);
return true;
}
/**
* Count number of possible moves from tile
* @param row Start row position.
* @param col Start columnt position.
* @return Number of possible moves from start position.
*/
private int countMoves(int row, int col) {
int possibleMoves = 0;
// Compute available moves for position
for (int secondIteration = 0; secondIteration < this.KNIGHT_MOVES_COUNT; secondIteration++) {
int nextRow = row + KNIGHT_MOVES[secondIteration][0];
int nextCol = col + KNIGHT_MOVES[secondIteration][1];
if (!isMovePossible(nextRow, nextCol) || isVisited(nextRow, nextCol)) {
continue;
}
possibleMoves++;
}
return possibleMoves;
}
/**
* Check if tile was already visited.
* @param row
* @param col
* @return True if position [row, col] was visited. Otherwise false.
*/
private boolean isVisited(int row, int col) {
return chessBoard[row][col] != 0;
}
/**
* Check if we can move to new position.
* @param row
* @param col
* @return True if move is possible to the position [row, col]. Otherwise false.
*/
private boolean isMovePossible(int row, int col) {
return (row >= 0) && (row < boardSize) && (col >= 0) && (col < boardSize);
}
/**
* Prints chessboard.
*/
public void printChessTable() {
for (int row = 0; row < boardSize; row++) {
for (int col = 0; col < boardSize; col++) {
System.out.print(chessBoard[row][col] + "\t");
}
System.out.println();
}
}
/**
* Main function. Starting point in program.
* @param args Command line parameters [chessboard size, starting row, starting col]
*/
public static void main(String []args) {
// Check number of arguments.
if (args.length < 3) {
System.err.println("Missing or incorrect command line arguments!\n" +
"Usage: solver.java [size] [row] [col]");
return;
}
int size, row, col;
// Check if command line arguments are valid. If not throw new error and stop program
try {
size = Integer.parseInt(args[0]);
row = Integer.parseInt(args[1]);
col = Integer.parseInt(args[2]);
if (col >= size || row >= size || col < 0 || row < 0) {
throw new IllegalArgumentException();
}
} catch(Exception e) {
System.err.println("Incorrect input!");
return;
}
Chessboard chessboard = new Chessboard(size);
long time = System.nanoTime();
boolean solved = chessboard.solvePuzzle(row, col);
time = System.nanoTime() - time;
if (solved) {
System.out.println("Solution was found!");
} else {
System.out.println("Solution was not found! ");
}
System.out.println(String.format("Computing time: %.2f ms.\nStart position: x=%d, y=%d. Last position: x=%d, y=%d.\n",
time / 1000000.f, row, col, chessboard.lastPosition.x, chessboard.lastPosition.y));
System.out.println("Chessboard:");
chessboard.printChessTable();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment