-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBoard.py
219 lines (185 loc) · 6.9 KB
/
Board.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
211
212
213
214
215
216
217
218
219
import random
import copy
class Board:
def __init__(self):
#creates a new, empty board
self.__resetBoard()
self.__resetUser()
self.spacesFilled = 0
# generate a random board
self.__generateRamdomBoard()
self.board_string = self.boardToboard_string()
def __getitem__(self,key):
return self.board[key]
def __resetUser(self):
self.user = [
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0]
]
return self.user
def __resetBoard(self):
self.board = [
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0]
]
return self.board
def boardToboard_string(self, input_board=None):
#returns stirng for other board
if input_board:
_board_string = ''.join([str(i) for j in input_board for i in j])
return _board_string
#returns the string for this board instance
else:
self.board_string = ''.join([str(i) for j in self.board for i in j])
return self.board_string
def findFirstEmpty(self):
for row in range(9):
for col in range(9):
if self.board[row][col] == 0:
return (row,col)
return False
def isValid(self,num,space):
#make sure space is empty
if not self.board[space[0]][space[1]] == 0:
return False
#make sure num is not in col
for col in self.board[space[0]]:
if col == num:
return False
#make sure num is not in row
for row in range(len(self.board)):
if self.board[row][space[1]] == num:
return False
boxR = space[0] // 3
boxC = space[1] // 3
#make sure num is not in the same 3x3 'box'
for i in range(3):
for j in range(3):
if self.board[i + (boxR * 3)][j + (boxC * 3)] == num:
return False
#if you've made it here, its a valid guess so far!
return True
def solve(self):
spacesAvailable = self.findFirstEmpty()
if not spacesAvailable:
return True
else:
row,col = spacesAvailable
numsAvail = [1,2,3,4,5,6,7,8,9]
for n in range(len(numsAvail)):
guess = random.choice(numsAvail)
numsAvail.remove(guess)
if self.isValid(guess,(row,col)):
self.board[row][col] = guess
if self.solve():
return True
self.board[row][col] = 0
numsAvail.append(guess)
return False
def __generateRamdomBoard(self):
#generate fill top left block randomly
_nums = list(range(1,10))
for row in range(3):
for col in range(3):
_num = random.choice(_nums)
self.board[row][col] = _num
_nums.remove(_num)
#same for center block
_nums = list(range(1,10))
for row in range(3,6):
for col in range(3,6):
_num = random.choice(_nums)
self.board[row][col] = _num
_nums.remove(_num)
#same for bottom left
_nums = list(range(1,10))
for row in range(6,9):
for col in range(6,9):
_num = random.choice(_nums)
self.board[row][col] = _num
_nums.remove(_num)
self.solve()
self.digger()
return self
def __findNthEmpty(self,board,n):
_index = 1
for row in range(9):
for col in range(9):
if board[row][col] == 0:
if _index == n:
return (row,col)
_index+=1
return (-1,-1)
def __solveForCreation(self,row,col):
for n in range(1,10):
if self.board[row][col]:
if self.solve():
return self.board
self.board[row][col] = 0
return False
def findNumberOfSolutions(self):
_index = 0
_listOfSolutions = []
for row in range(9):
for col in range(9):
if self.board[row][col] == 0:
_index += 1
for i in range(1,_index+1):
_boardCopy = copy.deepcopy(self)
_row, _col = self.__findNthEmpty(_boardCopy.board,i)
_boardCopySolution = _boardCopy.__solveForCreation(_row,_col)
_listOfSolutions.append(self.boardToboard_string(input_board=_boardCopySolution))
return list(set(_listOfSolutions))
def digger(self, spacesLeft = 81):
self.key = copy.deepcopy(self.board)
_numToRemove = 46
if spacesLeft < _numToRemove:
_numToRemove = spacesLeft
for i in range (0,3):
_counter = 0
while _counter < 4:
_rRow = random.randint((3 * i), 2 + (3 * i))
_rCol = random.randint((3 * i), 2 + (3 * i))
if self.board[_rRow][_rCol] != 0:
self.board[_rRow][_rCol] = 0
_counter += 1
_numToRemove -= 12
_counter = 0
while _counter < _numToRemove:
_row = random.randint(0,8)
_col = random.randint(0,8)
if self.board[_row][_col] != 0 and self.user[_row][_col] == 0:
n = self.board[_row][_col]
self.board[_row][_col] = 0
if len(self.findNumberOfSolutions()) != 1:
self.board[_row][_col] = n
continue
_counter += 1
return self.board, self.key
#TODO: Make a mehtod that adds user inputted tiles to the board.
def enterSpace(self, tile, num):
if self.board[tile[0]][tile[1]] == 0:
if self.key[tile[0]][tile[1]] != num:
print("key says this spot was supposed to be " + str(self.key[tile[0]][tile[1]]))
return False
self.user[tile[0]][tile[1]] = num
self.board = copy.deepcopy(self.user)
self.spacesFilled = self.spacesFilled + 1
self.solve()
self.digger(spacesLeft= 81 - self.spacesFilled)
return self.board, self.user, self.spacesFilled, True
print("Board was not empty")