Skip to main content
Post Made Community Wiki by risky mysteries
Source Link

All angles word search

With this program, you can put use any letter grid of any shape.

Here is how it goes:

enter image description here

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.