-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathn-pieces.py
210 lines (187 loc) · 7.9 KB
/
n-pieces.py
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
"""The N-pieces puzzle"""
# Further changes - mkings checking, noard array, changing board size, other pieces, etc.
class NPieces:
"""Generate all solutions for N-pieces puzzle for specified piece and board size"""
def __init__(self, size, piece):
# Store the puzzle (problem) size and the number of valid solutions
# add - row, col, num-pieces
self.size = size
self.piece = piece
self.solutions = 0
self.solve()
def solve(self):
"""Solve the N-pieces puzzle and print the number of solutions"""
positions = [-1] * self.size
if self.piece == "q" or "Q":
self.put_queen(positions, 0)
else:
if self.piece == "r" or "R":
self.put_rook(positions, 0)
else:
if self.piece == "k" or "K":
self.put_king(positions, 0)
else:
if self.piece == "b" or "B":
self.put_bishop(positions,0)
print("Found ", self.solutions, " solutions.")
print("Press the <ENTER> key to continue...")
input()
def put_queen(self, positions, target_row):
"""
Try to place a queen on target_row by checking all N possible cases.
If a valid place is found the functions recurses trying to place a queen
on the next row until all N pieces are placed on the NxN board.
"""
# Base case - all N rows are occupied
if target_row == self.size:
self.show_full_board(positions)
self.solutions += 1
else:
# For all N columns positions try to place a queen
for column in range(self.size):
# Reject all invalid positions
if self.check_place_queen(positions, target_row, column):
positions[target_row] = column
self.put_queen(positions, target_row + 1)
def put_rook(self, positions, target_row):
"""
Try to place a rook on target_row by checking all N possible cases.
If a valid place is found the functions recurses trying to place a rook
on the next row until all N pieces are placed on the NxN board.
"""
# Base case - all N rows are occupied
if target_row == self.size:
self.show_full_board(positions)
self.solutions += 1
else:
# For all N columns positions try to place a rook
for column in range(self.size):
# Reject all invalid positions
if self.check_place_rook(positions, column):
positions[target_row] = column
self.put_rook(positions, target_row + 1)
def put_bishop(self, positions, target_row):
"""
Try to place a bishop on target_row by checking all N possible cases.
If a valid place is found the functions recurses trying to place a bishop
on the next row until all N pieces are placed on the NxN board.
"""
# Base case - all N rows are occupied
if target_row == self.size:
self.show_full_board(positions)
self.solutions += 1
else:
# For all N columns positions try to place a bishop
for column in range(self.size):
# Reject all invalid positions
if self.check_place_bishop(positions, target_row, column):
positions[target_row] = column
self.put_bishop(positions, target_row + 1)
def put_king(self, positions, target_row):
"""
Try to place a king on target_row by checking all N possible cases.
If a valid place is found the functions recurses trying to place a king
on the next row until all N pieces are placed on the NxN board.
"""
# Base case - all N rows are occupied
if target_row == self.size:
self.show_full_board(positions)
self.solutions += 1
else:
# For all N columns positions try to place a queen
for column in range(self.size):
# Reject all invalid positions
if self.check_place_king(positions, target_row, column):
positions[target_row] = column
self.put_king(positions, target_row + 1)
def put_mking(self, positions, target_row):
"""
Try to place a mking on target_row by checking all N possible cases.
If a valid place is found the functions recurses trying to place a mking
on the next row until all N pieces are placed on the NxN board.
"""
# Base case - all N rows are occupied
if target_row == self.size:
self.show_full_board(positions)
self.solutions += 1
else:
# For all N columns positions try to place a queen
for column in range(self.size):
# Reject all invalid positions
if self.check_place_mking(positions, target_row, column):
positions[target_row] = column
self.put_mking(positions, target_row + 1)
def check_place_queen(self, positions, occupied_rows, column):
"""
Check if a given position is under attack from any of
the previously placed queens (check column and diagonal positions)
"""
for i in range(occupied_rows):
if positions[i] == column or \
positions[i] - i == column - occupied_rows or \
positions[i] + i == column + occupied_rows:
return False
return True
def check_place_rook(self, positions, column):
"""
Check if a given position is under attack from any of
the previously placed rooks (check column)
"""
if positions[i] == column:
return False
return True
def check_place_bishop(self, positions, occupied_rows, column):
"""
Check if a given position is under attack from any of
the previously placed queens (check diagonal positions)
"""
for i in range(occupied_rows):
if positions[i] - i == column - occupied_rows or \
positions[i] + i == column + occupied_rows:
return False
return True
def check_place_king(self, positions, occupied_rows, column):
"""
Check if a given position is under attack from any of
the previously placed kings (check column and diagonal positions)
"""
for i in range(occupied_rows):
if positions[i] == column or \
positions[i] - i == column - occupied_rows or \
positions[i] + i == column + occupied_rows:
return False
return True
def check_place_mking(self, positions, occupied_rows, column):
"""
Check if a given position is under attack from any of
the previously placed mkings (check column positions)
"""
for i in range(occupied_rows):
if positions[i] == column:
return False
return True
def show_full_board(self, positions):
"""Show the full NxN board"""
for row in range(self.size):
line = ""
for column in range(self.size):
if positions[row] == column:
line = line + self.piece + " "
else:
line += ". "
print(line)
print("\n")
"""
def main():
# Initialize and solve the n-pieces puzzle
NPieces(8,"Q")
if __name__ == "__main__":
# execute only if run as a script
main()
"""
def main(size, piece):
"""Initialize and solve the n-pieces puzzle"""
NPieces(size, piece)
if __name__ == "__main__":
# execute only if run as a script
main(size, piece)