0
votes

So I am making a program that is supposed to generate a random crossword puzzle. I have a method reads in a txt file that has a list of around 3000 words, stores it into an array list and returns the array list. I have a driver method which asks the user for the amount of rows and columns they want the crossword puzzle to be and from there it is supposed to generate a random puzzle. I'm using a 2d array to construct the entire puzzle but I can't figure out how to add words into the puzzle. This is what I have so far for the method that is supposed to fill in the crossword (the randomNumber method is just a method that returns a random index that is used to access a random word from the list)

public static void buildCrossword(ArrayList<String> words, int rows, int columns)      
{
    String[][] board = new String[rows][columns];
    //Picks a random number from the arrayList using a random index from the randomNumber method
    int randomNumber = randomNumber();
    String randomWord = words.get(randomNumber);

    //we remove it right after it is selected to ensure that it doesn't get used again in the puzzle
    words.remove(randomNumber);


    char[] temp = randomWord.toCharArray();
    char[][] word = new char[temp.length][temp.length];
    word[0] = temp;

    System.out.println("*----".repeat(rows) + "*");
    for(int i = 0; i < columns; i++)
    {
        System.out.println("|    ".repeat(rows) + "|");
        System.out.println(word[0][i]);
        System.out.println("*----" .repeat(rows) + "*");
    }
}

As you know own a crossword there are also filled in unused squares and I need to use an "*" to represent the unused squares. Any help at all would be appreciated.

1

1 Answers

0
votes

You should separate your "showing the crossword" logic from your "filling in the crossword" logic. Typically, you would build a Crossword class that contains the 2d array of characters inside (you have a 2d array of Strings - but I believe characters are better), and would provide a toString() method to do the "showing the crossword". You could also have an addWord(String word) method to add a word into the crossword -- the currently-missing part of your code.

Building a crossword would require:

  • creating an empty, new Crossword(rows, cols)

  • in a loop, choosing words to add until it is full; and, for each word, adding it:

    boolean full = false;
    while ( ! full) {
       // choose a word
       int randomNumber = randomNumber();
       String randomWord = words.get(randomNumber);
       words.remove(randomNumber);
    
       // try to add it
       if ( ! crossword.addWord(randomWord)) {
          full = true;
       }
    }
    

Adding a word requires searching for an empty space where you can place it, but to save space and get a crossword, you actually want to share at least a single letter with an existing word on the crossword -- except for the 1st word placed, which cannot share anything. If your crossword looks like this, it is easier to know if it is empty:

  public class Crossword {
     private Char[][] letters;
     private int rows, cols;
     private int totalWords; // incremented by 1 after each successful addWord
     
     public boolean addWord(String word) { /* your implementation here */}   
     public String toString() { /* your printing code here */ }
  }

The hardest part is, without doubt, the "find where to fit a new word" logic from addWord. You can make it easier with some helper methods:

     // inside Crossword class
  
     // returns true if word fits vertically with 1st letter at letters[col][row]
     private boolean fitsVertical(int row, int col, String word);

     // returns true if word fits horizontally with 1st letter at letters[col][row]
     private boolean fitsHorizontal(int row, int col, String word);