Search code examples
pythongridcrossword

How to generate a word search grid that enables words using the same letter


I'm trying to make a word-search grid with a list of given words. My problem is that some of the words don't appear properly.

I have updated the code, see below

I have tried to fix the previous error and now I am getting an out of range error that i cant fix, if anyone can help I would appreciate

Note 1: I didnt include all the program functions, if required I will include them later

The program takes in a text file like this:

9 9  
white  
black  
blue  
green  
pink  
yellow  
red  
grey  
purple  

where the first 2 numbers in the file are the dimensions of the grid, and the rest is the words to place in the grid.

import random
import string
fi=input('Insert the entry file name(entry.txt): ')
fo=input('Insert the exit file name(.txt): ')
grid_size=[]
words=[]
matrix=[]

def read_file(storage):
    file=open(storage)

    n=file.readline()
    lista=n.split()
    lista=list(map(int,lista))  #sets the size of the grid
    for i in lista:
        grid_size.append(i)

    for line in file:
        line=line.replace("\n","")
        words.append(line)
    file.close()

def grid_generator(grid_size):
    n, p = grid_size
    for i in range(n):
        matriz.append([])
        for j in range(p):
            matriz[i].append(".")   

def sets_word_inside(grid_size, word, grid):
      n, p = grid_size
      word = random.choice([word,word[::-1]])  
                #horizontal,vertical,diagonal
      d = random.choice([[1,0],[0,1],[1,1]]) 

      xsize = n  if d[0] == 0 else n  - len(word)
      ysize = p if d[1] == 0 else p - len(word)

      x= random.randrange(0,xsize)
      y= random.randrange(0,ytsize)  #position

      for i, letter in enumerate(word):
           char = grid[y+d[1]*i][x+d[0]*i]   
           if char != " " and char != letter:
               # If it reaches an already filled space - restart the            process.
               # The second condition allow the words that cross with repeated words are created.

               return False
           grid[y+d[1]*i][x+d[0]*i] = letter[i]
      return True

For now the output of the code is something like this:

9  
white  
black  
blue  
green  
pink  
yellow  
red  
grey  
purple  
p w b i t y l d i  
p v w o l e e y t  
x g a x j r i m g  
q i c j b g j e x  
s s k g q l g r r  
p i n k i o u t r  
e l p r u p g e o  
l a b l s r p g y  
c o r y e u f r x  

Solution

  • I see two basic problems: you overwrite existing words with new ones, and you write beyond the end of the actual word.

    The first problem is that you haven't bothered to look for prior words before you add new ones. The second problem is because you fail to strip white-space out of the input.

    I added some simple debugging instrumentation to track this. First, I initialised the grid to dots instead of letters, so I could see what's going on:

    for j in range(p):
        matrix[i].append(".")
    

    Then, I printed the matrix after adding each word:

    for i in range(0,len(word)):
        grid[y+d[1]*i][x+d[0]*i]=word[i]
    
    print "\nUpdated grid with\t", word, "\n",
    for row in range(n):
        print " ".join(matrix[row])
    
    return grid
    

    Then I ran it and got this output:

    Updated grid with   white   
    . . . . . . . . .
    . . . . . . . . .
    . w h i t e     .
    . . . . . . . . .
    . . . . . . . . .
    . . . . . . . . .
    . . . . . . . . .
    . . . . . . . . .
    . . . . . . . . .
    
    Updated grid with     kcalb 
    .   . . . . . . .
    . .   . . . . . .
    . w h k t e     .
    . . . . c . . . .
    . . . . . a . . .
    . . . . . . l . .
    . . . . . . . b .
    . . . . . . . . .
    . . . . . . . . .
    
    Updated grid with   blue   
    .   . . . . . . .
    . . b . . . . . .
    . w h l t e     .
    . . . . u . . . .
    . . . . . e . . .
    . . . . . .   . .
    . . . . . . .   .
    . . . . . . . . .
    . . . . . . . . .
    
    Updated grid with     neerg 
        . . . . . . .
    .   b . . . . . .
    . w n l t e     .
    . . . e u . . . .
    . . . . e e . . .
    . . . . . r   . .
    . . . . . . g   .
    . . . . . . . . .
    . . . . . . . . .
    

    You see what's happening: you write too far, and you crash over existing entries.

    SOLUTION

    I recommend that you follow what I've done so far: initialize to some non-letter that you find easy to read. Now, before you enter a word into the grid check that the path is clear. Even better, allow for writing across previous words if the intersecting letters match.

    After you've placed all the words from the list, then fill in the rest of the grid.