-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathKnightsTourGreedy.java
More file actions
141 lines (119 loc) · 5.04 KB
/
KnightsTourGreedy.java
File metadata and controls
141 lines (119 loc) · 5.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import java.util.Scanner;
/**
* Task 2 – Knight's Tour (Greedy / Warnsdorff's Rule)
*
* Finds a CLOSED Knight's Tour on an n×n chessboard using a greedy algorithm
* that tries every (startX, startY) × first-move combination.
*
* Time complexity: O(n²)
*/
public class KnightsTourGreedy {
// Direction arrays for the 8 possible moves of a knight
private static int[] knightMovesX = {-2, -1, 1, 2, 2, 1, -1, -2};
private static int[] knightMovesY = { 1, 2, 2, 1, -1, -2, -2, -1};
private static int[][] chessboard;
private static int boardSize;
// Check if the given position (x, y) is valid (inside the board and unvisited)
private static boolean isValidMove(int x, int y) {
return x >= 0 && y >= 0 && x < boardSize && y < boardSize && chessboard[x][y] == -1;
}
// Get the number of valid moves from a given position (x, y) – Warnsdorff's rule
private static int getMoveDegree(int x, int y) {
int validMoves = 0;
for (int i = 0; i < 8; i++) {
int newX = x + knightMovesX[i];
int newY = y + knightMovesY[i];
if (isValidMove(newX, newY)) {
validMoves++;
}
}
return validMoves;
}
/**
* Perform a greedy knight's tour starting from (startX, startY),
* with (firstMoveX, firstMoveY) as the first move.
*/
private static boolean performGreedyTour(int startX, int startY,
int firstMoveX, int firstMoveY) {
int currentX = firstMoveX;
int currentY = firstMoveY;
// Mark the starting position and the first move on the board
chessboard[startX][startY] = 0;
chessboard[currentX][currentY] = 1;
int moveCount = boardSize * boardSize - 1;
for (int move = 2; move <= moveCount; move++) {
int bestX = -1, bestY = -1;
int minDegree = Integer.MAX_VALUE;
for (int i = 0; i < 8; i++) {
int newX = currentX + knightMovesX[i];
int newY = currentY + knightMovesY[i];
if (isValidMove(newX, newY)) {
int degree = getMoveDegree(newX, newY);
if (degree < minDegree) {
minDegree = degree;
bestX = newX;
bestY = newY;
}
}
}
if (bestX == -1) return false; // stuck
chessboard[bestX][bestY] = move;
currentX = bestX;
currentY = bestY;
}
// Check if the final move can return to the starting position (closed tour)
for (int i = 0; i < 8; i++) {
if (currentX + knightMovesX[i] == startX &&
currentY + knightMovesY[i] == startY) {
System.out.println("Closed Knight's Tour found with " +
moveCount + " moves.");
return true;
}
}
return false; // no closed tour found
}
// Print the final chessboard showing the knight's tour path
private static void printChessboard() {
for (int i = 0; i < boardSize; i++) {
for (int j = 0; j < boardSize; j++) {
System.out.print(chessboard[i][j] + "\t");
}
System.out.println();
}
}
// Main method to execute the knight's tour
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter the size of the chessboard (n x n): ");
boardSize = scanner.nextInt();
boolean tourFound = false;
// Try all starting positions (startX, startY)
outer:
for (int startX = 0; startX < boardSize; startX++) {
for (int startY = 0; startY < boardSize; startY++) {
// Try all 8 possible directions for the first move
for (int direction = 0; direction < 8; direction++) {
int firstMoveX = startX + knightMovesX[direction];
int firstMoveY = startY + knightMovesY[direction];
if (firstMoveX >= 0 && firstMoveY >= 0 &&
firstMoveX < boardSize && firstMoveY < boardSize) {
// Initialize chessboard with -1 (unvisited)
chessboard = new int[boardSize][boardSize];
for (int i = 0; i < boardSize; i++)
for (int j = 0; j < boardSize; j++)
chessboard[i][j] = -1;
if (performGreedyTour(startX, startY, firstMoveX, firstMoveY)) {
System.out.println("Start position: (" + startX + ", " + startY + ")");
printChessboard();
tourFound = true;
break outer;
}
}
}
}
}
if (!tourFound) {
System.out.println("No closed Knight's Tour found using greedy.");
}
}
}