Размещение кроссворда в tkinter
У меня имеется код на python, но мне нужен графический интерфейс tkinter, чтобы кроссворд выводился в отдельном окне с вопросами. Поскольку на решение кроссворда программа не заточена, возможно ли дополнить данный код, чтобы в окне выводился кроссворд, и при нажатии на кнопку, он пересоздавался с другим положением слов. То есть происходило бы тоже самое, что и в консоли? И если возможно, хотелось бы увидеть как.
from operator import itemgetter
from collections import defaultdict
class Crossword:
def __init__(self, rows, cols, empty=' ', available_words=[]):
self.rows = rows
self.cols = cols
self.empty = empty
self.available_words = available_words
self.let_coords = defaultdict(list)
def prep_grid_words(self):
self.current_wordlist = []
self.let_coords.clear()
self.grid = [[self.empty]*self.cols for i in range(self.rows)]
self.available_words = [word[:2] for word in self.available_words]
self.first_word(self.available_words[0])
def compute_crossword(self, time_permitted=1.00):
self.best_wordlist = []
wordlist_length = len(self.available_words)
time_permitted = float(time_permitted)
start_full = float(time.time())
while (float(time.time()) - start_full) < time_permitted:
self.prep_grid_words()
[self.add_words(word) for i in range(2) for word in self.available_words
if word not in self.current_wordlist]
if len(self.current_wordlist) > len(self.best_wordlist):
self.best_wordlist = list(self.current_wordlist)
self.best_grid = list(self.grid)
if len(self.best_wordlist) == wordlist_length:
break
answer = '\n'.join([''.join([u'{} '.format(c) for c in self.best_grid[r]])
for r in range(self.rows)])
return answer + '\n\n' + str(len(self.best_wordlist)) + ' out of ' + str(wordlist_length)
def get_coords(self, word):
"""Получение возможных координат для каждой буквы."""
word_length = len(word[0])
coordlist = []
temp_list = [(l, v) for l, letter in enumerate(word[0])
for k, v in self.let_coords.items() if k == letter]
for coord in temp_list:
letc = coord[0]
for item in coord[1]:
(rowc, colc, vertc) = item
if vertc:
if colc - letc >= 0 and (colc - letc) + word_length <= self.cols:
row, col = (rowc, colc - letc)
score = self.check_score_horiz(word, row, col, word_length)
if score:
coordlist.append([rowc, colc - letc, 0, score])
else:
if rowc - letc >= 0 and (rowc - letc) + word_length <= self.rows:
row, col = (rowc - letc, colc)
score = self.check_score_vert(word, row, col, word_length)
if score:
coordlist.append([rowc - letc, colc, 1, score])
if coordlist:
return max(coordlist, key=itemgetter(3))
else:
return
def first_word(self, word):
"""Поместить первое слово в произвольную позицию в сетке."""
vertical = random.randrange(0, 2)
if vertical:
row = random.randrange(0, self.rows - len(word[0]))
col = random.randrange(0, self.cols)
else:
row = random.randrange(0, self.rows)
col = random.randrange(0, self.cols - len(word[0]))
self.set_word(word, row, col, vertical)
def add_words(self, word):
"""Добавление остальных слов."""
coordlist = self.get_coords(word)
if not coordlist:
return
row, col, vertical = coordlist[0], coordlist[1], coordlist[2]
self.set_word(word, row, col, vertical)
def check_score_horiz(self, word, row, col, word_length, score=1):
cell_occupied = self.cell_occupied
if col and cell_occupied(row, col-1) or col + word_length != self.cols and cell_occupied(row, col + word_length):
return 0
if row and (not cell_occupied(row-1, col) and cell_occupied(row, col) and (row+1 == self.rows or cell_occupied(row+1, col))):
return 0
if not row and cell_occupied(row, col):
return 0
for letter in word[0]:
active_cell = self.grid[row][col]
if active_cell == self.empty:
if row + 1 != self.rows and cell_occupied(row+1, col) or row and cell_occupied(row-1, col):
return 0
elif active_cell == letter:
score += 1
else:
return 0
col += 1
return score
def check_score_vert(self, word, row, col, word_length, score=1):
cell_occupied = self.cell_occupied
if row and cell_occupied(row-1, col) or row + word_length != self.rows and cell_occupied(row + word_length, col):
return 0
if col and (not cell_occupied(row, col-1) and cell_occupied(row, col) and (col+1 == self.cols or cell_occupied(row, col+1))):
return 0
if not col and cell_occupied(row, col):
return 0
for letter in word[0]:
active_cell = self.grid[row][col]
if active_cell == self.empty:
if col + 1 != self.cols and cell_occupied(row, col+1) or col and cell_occupied(row, col-1):
return 0
elif active_cell == letter:
score += 1
else:
return 0
row += 1
return score
def set_word(self, word, row, col, vertical):
""" Добавление слов в список слов."""
word.extend([row, col, vertical])
self.current_wordlist.append(word)
horizontal = not vertical
for letter in word[0]:
self.grid[row][col] = letter
if (row, col, horizontal) not in self.let_coords[letter]:
self.let_coords[letter].append((row, col, vertical))
else:
self.let_coords[letter].remove((row, col, horizontal))
if vertical:
row += 1
else:
col += 1
def cell_occupied(self, row, col):
cell = self.grid[row][col]
if cell == self.empty:
return False
else:
return True
class Word:
def __init__(self, word=None, clue=None):
self.word = re.sub(r'\s', '', word.lower())
self.clue = clue
self.length = len(self.word)
# the below are set when placed on board
self.row = None
self.col = None
self.vertical = None
self.number = None
def down_across(self): # return down or across
if self.vertical:
return 'по вертикали'
else:
return 'по горизонтали'
if __name__ == "__main__":
ncol, nrow = 30, 30
wordlist = [[line.split(':')[0].upper(), line.split(':')[1]] for line in open('words.txt').read().splitlines()]
wordlist = wordlist[:]
cw = Crossword(nrow, ncol, ' ', wordlist)
print(cw.compute_crossword())`