- Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathKnightTour.py
More file actions
Latest commit
111 lines (95 loc) · 3.02 KB
/
Copy pathKnightTour.py
File metadata and controls
111 lines (95 loc) · 3.02 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
#!/usr/bin/env python
'''
A knight's tour is a sequence of moves of a knight on a chessboard
such that the knight visits every square exactly once.
If the knight ends on a square that is one knight's move
from the beginning square (so that it could tour the board again
immediately, following the same path), the tour is closed, otherwise it is open.
warnsdorff's rule
move the knight to the squere whose next move has fewest onward moves.
'''
fromBoardimport*
importsys
importunittest
VERBOSE=True
# next moves for the knight
MOVES= [{'x':-2, 'y':-1},{'x':-1,'y':-2},{'x':1,'y':-2},{'x':2,'y':-1},
{'x':2,'y':1},{'x':1,'y':2},{'x':-1,'y':2},{'x':-2,'y':1}]
classKnightsTourBoard(Board):
'''
create board for knight tour including the rule for solving knight tour game
'''
def__init__(self, num_rows=8, num_cols=8):
super(KnightsTourBoard, self).__init__(
num_rows=num_rows, num_cols=num_cols, init_char=" ")
defcanPlaced(self,point):
'''
check whether the knight can place here if it is not visited before
'''
returnself[point] !='K'
defnextMoves(self,point):
'''
given the current position for the knight, return the available next moves
'''
next_moves= []
formoveinMOVES:
nextPos=Point(point.row+move['y'], point.col+move['x'])
# print "%d,%d" % (nextPos.row, nextPos.col)
printnextPos
ifself.isValid(nextPos) andself.canPlaced(nextPos):
next_moves.append(nextPos)
returnnext_moves
defknightTour(self,path,move):
'''
Determine whether there is a path for the knight to traverse the board
Args:
path: valid moves for the knight
move: the current move
Return:
True if there is a solution for the knight
'''
ifVERBOSE:
printself
maxSteps=self.numRows*self.numCols
# Check if we're done and return True.
ifall([all(c=="K"forcinrow) forrowinself._rows]):
returnTrue
ifVERBOSE:
print"I'm at: %s"%move
# Calculate the next moves.
nexts=self.nextMoves(move)
ifVERBOSE:
print"nexts: %s"% ["%s"%mforminnexts]
ifnotnexts:
returnFalse
# Order moves by most-restrictive first.
fornextinsorted(nexts, key=lambdax: len(self.nextMoves(x))):
path.append(next)
# mark the position that knight visited
self[next] ='K'
ifself.knightTour(path, next):
returnTrue
else:
ifVERBOSE:
print"Backtracking!"
self[next] ='x'
path.pop()
returnFalse
# print the kight path
# Args: path which consist of all Point instance
defprintPath(path):
print"%s"%", ".join([str(p) forpinpath])
defmain():
# number of rows and columns for the board
# initiate the board
B=KnightsTourBoard(6, 6)
# knight path
path= []
# starting position for the knight
start=Point(2, 2)
B[start] ="K"
ifnotB.knightTour(path,start):
print"solution doesn't exist"
else:
printPath(path)
main()