1. Anuncie Aqui ! Entre em contato fdantas@4each.com.br

[Python] Fixing Python wordsearch diagonal highlighting issue

Discussão em 'Python' iniciado por Stack, Outubro 7, 2024 às 09:32.

  1. Stack

    Stack Membro Participativo

    So, I was building this Python word search program, which searches through the X*X grid of letters and draws highlights over found words. It works fine for horizontal and vertical words, but I was having difficulty with diagonal ones, as you can see in this image:

    [​IMG]

    It draws highlights over other words, too. I tried the bound box approach but haven't got the desired results.

    So, can any of you help with this, please?

    import random
    import string
    from PIL import Image, ImageDraw, ImageFont

    def create_grid(words, shape='rectangle', size=10,sizer=5): #Sizer is and extra argument used just for rectangle,as it has dimensions(length and width) of different lengths
    if shape == 'rectangle':
    grid = create_rectangular_grid(size,sizer)
    elif shape == 'square':
    grid = create_rectangular_grid(size, size) # Using same function for square as it's just a rectangle with equal dimesnions(length and width)
    elif shape == 'circle':
    grid = create_circular_grid(size)
    elif shape == 'heart':
    grid = create_heart_grid(size)
    else:
    raise ValueError("Unsupported shape. Choose 'rectangle', 'square', 'circle', or 'heart'.")

    for word in words:
    place_word(grid, word)

    fill_empty_spaces(grid)
    return grid


    def create_rectangular_grid(width, height):
    return [[' ' for _ in range(width)] for _ in range(height)]

    def create_circular_grid(diameter):
    grid = [[None for _ in range(diameter)] for _ in range(diameter)]
    center = diameter // 2
    radius = diameter // 2
    for y in range(diameter):
    for x in range(diameter):
    if (x - center)**2 + (y - center)**2 <= radius**2:
    grid[y][x] = ' '
    return grid

    def create_heart_grid(size):
    grid = [[None for _ in range(size)] for _ in range(size)]
    for y in range(size):
    for x in range(size):
    if in_heart(x, y, size):
    grid[y][x] = ' '
    return grid

    def in_heart(x, y, size):
    # Heart curve formula
    x = (2 * x - size + 1) / size
    y = (2 * y - size + 1) / size
    return (x*x + y*y - 1)**3 - x*x * y*y*y <= 0

    def place_word(grid, word):
    height, width = len(grid), len(grid[0])
    placed = False
    attempts = 0
    max_attempts = 100

    while not placed and attempts < max_attempts:
    direction = random.choice(['horizontal', 'vertical', 'diagonal'])
    x, y = random.randint(0, width - 1), random.randint(0, height - 1)

    if can_place_word(grid, word, x, y, direction):
    do_place_word(grid, word, x, y, direction)
    placed = True

    attempts += 1

    if not placed:
    print(f"Failed to place word: {word}")

    def can_place_word(grid, word, x, y, direction):
    height, width = len(grid), len(grid[0])
    if direction == 'horizontal' and x + len(word) <= width:
    return all(grid[y][x+i] in [' ', word] for i in range(len(word)))
    elif direction == 'vertical' and y + len(word) <= height:
    return all(grid[y+i][x] in [' ', word] for i in range(len(word)))
    elif direction == 'diagonal' and x + len(word) <= width and y + len(word) <= height:
    return all(grid[y+i][x+i] in [' ', word] for i in range(len(word)))
    return False

    def do_place_word(grid, word, x, y, direction):
    if direction == 'horizontal':
    for i, letter in enumerate(word):
    grid[y][x + i] = letter
    elif direction == 'vertical':
    for i, letter in enumerate(word):
    grid[y + i][x] = letter
    elif direction == 'diagonal':
    for i, letter in enumerate(word):
    grid[y + i][x + i] = letter

    def fill_empty_spaces(grid):
    for row in grid:
    for i in range(len(row)):
    if row == ' ':
    row = random.choice(string.ascii_uppercase)

    def draw_grid(grid, words, cell_size=50, font_path='./robotob.ttf', output_file='word_search.png'): # Customise font
    height, width = len(grid), len(grid[0])
    img_size = (width * cell_size, height * cell_size)
    img = Image.new('RGB', img_size, color='white')
    draw = ImageDraw.Draw(img)
    font = ImageFont.truetype(font_path, int(cell_size * 0.7))

    # Draw the letters
    for y, row in enumerate(grid):
    for x, letter in enumerate(row):
    if letter is not None:
    draw.text((x * cell_size + cell_size/4, y * cell_size), letter, font=font, fill='black')

    # Highlight words with rounded rectangles and pass font
    for word in words:
    highlight_word(draw, grid, word, cell_size, font)

    img.save(output_file)


    def highlight_word(draw, grid, word, cell_size, font):
    height, width = len(grid), len(grid[0])
    for y in range(height):
    for x in range(width):
    if grid[y][x] == word[0]:
    directions = [
    (1, 0), # horizontal
    (0, 1), # vertical
    (1, 1), # diagonal
    ]
    for dx, dy in directions:
    if check_word(grid, word, x, y, dx, dy):
    draw_highlight(draw, x, y, len(word), dx, dy, cell_size, font)


    def check_word(grid, word, x, y, dx, dy):
    height, width = len(grid), len(grid[0])
    if not all(0 <= x + i*dx < width and 0 <= y + i*dy < height for i in range(len(word))):
    return False
    return all(grid[y + i*dy][x + i*dx] == letter for i, letter in enumerate(word))

    def draw_highlight(draw, x, y, length, dx, dy, cell_size, font):
    padding = 5
    start = (x * cell_size - padding, y * cell_size - padding)
    end = ((x + dx * (length - 1)) * cell_size + cell_size + padding,
    (y + dy * (length - 1)) * cell_size + cell_size + padding)

    # Draw a black filled rounded rectangle
    draw.rounded_rectangle([start, end], radius=15, fill='black')

    # Draw the word in white on top of the black rectangle
    for i in range(length):
    tx = (x + i * dx) * cell_size + cell_size / 4
    ty = (y + i * dy) * cell_size
    draw.text((tx, ty), grid[y + i * dy][x + i * dx], font=font, fill='white')



    # Example usage for wordsearch
    words = ['JANE', 'LUKAS', 'BOB']
    grid = create_grid(words, shape='rectangle', size=15,sizer=10) # Arguments can be modified with different parameteres,it will overwrite defualt parametres used above in the function
    draw_grid(grid, words, output_file='bw_search.png') # Generated imagefilename and path can be modified,by default it saves the image in the same folder


    I was having issues with highlighting diagonal words in a word search program, so I would like someone to help me resolve this issue.

    Continue reading...

Compartilhe esta Página