All angles word search
With this program, you can put use any letter grid of any shape.
Here is how it goes:
As shown in the demonstration, you can type in anything into the text box as long as it's in the alphabet or a space. Then the program will highlight all the series of cells in the grid that makes up the word. You can also edit the grid by clicking on the cells during run-time.
Here is the code:
import pygame
pygame.font.init()
wn = pygame.display.set_mode((600, 600))
letters = \ # You can customize this grid with letter of the alphabet and spaces
'''
KJDJCIOSDZ
PGRIWOTAID
VETVALCGLS
OFZESGZASW
SOYRBKOADL
FUWTQOXNGE
CILIWMEPAV
NEZCJRVZNL
GXZAOQMFIG
EUPLIESCGP
HORIZONTAL
'''
class Cell():
def __init__(self, x, y, s, text='', color=(0, 0, 0), cell=True):
self.input_box = pygame.Rect(x, y, s, s)
self.x = x
self.y = y
self.s = s
self.w = s
self.color_inactive = color
self.color_active = pygame.Color('purple')
self.color = self.color_inactive
self.text = text
self.active = False
self.pad = 10
self.cell = cell
self.font = pygame.font.Font(None, s)
def check_status(self, pos):
if self.input_box.collidepoint(pos):
self.active = not self.active
else:
self.active = False
self.color = self.color_active if self.active else self.color_inactive
def type(self, event):
if self.active:
if self.cell:
if event.unicode and event.unicode.lower() in 'abcdefghijklmnopqrstuvwxyz ':
self.text = event.unicode
else:
if event.key == pygame.K_BACKSPACE:
self.text = '' if len(self.text) < 2 else self.text[:-1]
elif event.unicode and event.unicode.lower() in 'abcdefghijklmnopqrstuvwxyz ':
self.text += event.unicode
def draw(self):
txt = self.font.render(self.text, True, self.color)
if not self.cell:
width = max(self.w, txt.get_width())
self.input_box.w = width + self.pad * 2
x = self.x + self.pad
else:
x = self.x+(self.s-txt.get_width())//2
y = self.y+(self.s-txt.get_height())*5//7
wn.blit(txt, (x, y))
pygame.draw.rect(wn, self.color, self.input_box, 2)
class Grid():
def __init__(self, x, y, size, letters, color=(0, 0, 0)):
rows = len(letters)
cols = len(letters[0])
self.grid = [[Cell(i*size+x, j*size+y, size, letter) for i, letter in enumerate(row)] for j, row in enumerate(letters)]
self.cells = [cell for row in self.grid for cell in row]
self.rows = rows
self.cols = cols
def check_status(self, pos):
for cell in self.cells:
cell.check_status(pos)
def type(self, event):
for cell in self.cells:
cell.type(event)
def adj(self, c, idx, lstlst, wrd):
x, y = self.cells.index(c) % self.cols, self.cells.index(c) // self.cols
x1, x2 = max(0, x - 1), min(x + 2, self.cols + 2)
y1, y2 = max(0, y - 1), min(y + 2, self.rows + 2)
adjs = [cell for row in self.grid[y1:y2] for cell in row[x1:x2] if cell != c]
taillst = lstlst[-1]
for cell in adjs:
if len(wrd) > idx:
if cell.text == wrd[idx] and cell not in taillst:
lstlst.append(taillst[:] + [cell])
self.adj(cell, idx+1, lstlst, wrd)
def draw(self):
for cell in self.cells:
cell.draw()
grid = Grid(50, 70, 32, list(filter(None, letters.split('\n'))))
word = Cell(50, 20, 32, cell=False)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
elif event.type == pygame.MOUSEBUTTONDOWN:
grid.check_status(event.pos)
word.check_status(event.pos)
elif event.type == pygame.KEYDOWN:
grid.type(event)
word.type(event)
for cell in grid.cells:
cell.color = (0, 0, 0)
for cell in grid.cells:
lstlst = [[cell]]
grid.adj(cell, 1, lstlst, word.text)
for lst in lstlst:
if ''.join([c.text for c in lst]) == word.text:
for c in lst:
c.color = (255, 0, 0)
wn.fill((255, 255, 255))
grid.draw()
word.draw()
pygame.display.flip()
If you scroll down you will see
grid = Grid(50, 70, 32, list(filter(None, letters.split('\n'))))
You can change the size of each cell in the grid by changing the third argument: 32
.
50
and 70
are the x, y positions of the entire grid.