SHOW:
|
|
- or go back to the newest paste.
1 | # knightstour.py | |
2 | # | |
3 | # created by: M. Peele | |
4 | # section: 01 | |
5 | # | |
6 | # This program implements a brute-force solution for the Knight's tour problem | |
7 | # using a recursive backtracking algorithm. The Knight's tour is a chessboard | |
8 | # puzzle in which the objective is to find a sequence of moves by the knight in | |
9 | # which it visits every square on the board exactly one. It uses a 6x6 array for | |
10 | # the chessboard where each square is identified by a row and column index, the | |
11 | # range of which both start at 0. Let the upper-left square of the board be the | |
12 | # row 0 and column 0 square. | |
13 | # | |
14 | # Imports the necessary modules. | |
15 | ||
16 | # Initializes the chessboard as a 6x6 array. | |
17 | chessBoard = [[None for i in range(6)] for j in range(6)] | |
18 | ||
19 | # Gets the input start position for the knight from the user. | |
20 | row = int(input("Enter the row: ")) | |
21 | col = int(input("Enter the column: ")) | |
22 | ||
23 | # Main driver function which starts the recursion. | |
24 | def main(): | |
25 | knightsTour(row, col, 1) | |
26 | ||
27 | # Recursive function that solves the Knight's Tour problem. | |
28 | def knightsTour(row, col, move): | |
29 | # Checks if the given index is in range of the array and is legal. | |
30 | if _inRange(row, col) and _isLegal(row, col): | |
31 | chessBoard[row][col] = move # Sets a knight-marker at the given index. | |
32 | # If the chessBoard is full, returns True and the solved board. | |
33 | if _isFull(chessBoard): | |
34 | return True, _draw(chessBoard) | |
35 | ||
36 | # Checks to see if the knight can make another move. If so, makes that | |
37 | # move by calling the function again. | |
38 | possibleOffsets = ((-2, -1), (-2, 1), (-1, 2), (1, 2), \ | |
39 | (2, 1), (2, -1), (1, -2), (-1, -2)) | |
40 | for offset in possibleOffsets: | |
41 | if knightsTour(row + offset[0], col + offset[1], move + 1): | |
42 | return True | |
43 | # If the loop terminates, no possible move can be made. Removes the | |
44 | # knight-marker at the given index. | |
45 | chessBoard[row][col] = None | |
46 | return False | |
47 | else: | |
48 | return False | |
49 | ||
50 | # Determines if the given row, col index is a legal move. | |
51 | def _isLegal(row, col): | |
52 | if _inRange(row, col) and chessBoard[row][col] == None: | |
53 | return True | |
54 | else: | |
55 | return False | |
56 | ||
57 | # Determines if the given row, col index is in range. | |
58 | def _inRange(row, col): | |
59 | try: | |
60 | chessBoard[row][col] | |
61 | return True | |
62 | except IndexError: | |
63 | return False | |
64 | ||
65 | # A solution was found if the array is full, meaning that every element in the | |
66 | # array is filled with a number saying the knight has visited there. | |
67 | def _isFull(chessBoard): | |
68 | for row in chessBoard: | |
69 | for col in row: | |
70 | if col is None: | |
71 | return False | |
72 | return True | |
73 | ||
74 | # Draws a pictoral representation of the array. | |
75 | def _draw(chessBoard): | |
76 | for row in chessBoard: | |
77 | for col in row: | |
78 | print("%4s" % col, end = " ") | |
79 | print() | |
80 | ||
81 | # Calls the main function. | |
82 | main() |