Question

Am experiencing a problem when generating a word search puzzle of 20 x 20. The puzzle is generated from a wordlists and words placed randomly. Problem is some words are being placed outside the grid! as seen here:

Screenshot

I have not filled the remaining buttons with random so as to get a clear picture of what is happening. Below is the code for generating the puzzle.

package wordsearch;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;

public class PuzzleGenerator {

    Character[][] thePuzzle = null;
    int _rows;
    int _cols;

    ArrayList<String> _wordList;

    private Random random = new Random();

    public PuzzleGenerator(int Rows, int Cols, ArrayList<String> wordList) {
        thePuzzle = new Character[Rows][Cols];

        this._rows = Rows;
        this._cols = Cols;
        this._wordList = wordList;

        for (int i = 0; i < this._rows; i++) {
            for (int j = 0; j < this._cols; j++) {
                thePuzzle[i][j] = '-';
            }
        }

        addWords();
    }

    public Character[][] getPuzzle(){
        return thePuzzle;
    }

    private char getCharAt(int x, int y) {
        char result = this.thePuzzle[x][y];
        return result;
    }

    private int getRows(PuzzleGenerator aPuzzle) {
        return this._rows;
    }

    private int getCols(PuzzleGenerator aPuzzle) {
        return this._cols;
    }

    private void addWords() {

        while (_wordList.size() != 0) {
            //put the first word from the list into a string
            String aWord = (String) _wordList.get(0);
            //remove the word from the list
            _wordList.remove(0);
            int numTries = 0;

            while (numTries < _rows * _cols) {
                //Choose a random location on the puzzle to start placement of word
                int startRow = random.nextInt(_rows);
                int startCol = random.nextInt(_cols);

                if (this.move(aWord, startRow, startCol, -1, 0)) {
                    break;
                }
                if (this.move(aWord, startRow, startCol, -1, 1)) {
                    break;
                }
                if (this.move(aWord, startRow, startCol, 0, 1)) {
                    break;
                }
                if (this.move(aWord, startRow, startCol, 1, 1)) {
                    break;
                }
                if (this.move(aWord, startRow, startCol, 1, 0)) {
                    break;
                }
                if (this.move(aWord, startRow, startCol, 1, -1)) {
                    break;
                }
                if (this.move(aWord, startRow, startCol, 0, -1)) {
                    break;
                }
                if (this.move(aWord, startRow, startCol, -1, -1)) {
                    break;
                }

                if (++numTries == _rows * _cols) {
                    System.err.println(aWord);
                }
            }
        }
    }
    private boolean move(String theWord, int startRow, int startCol, int dx, int dy) {
        boolean result = true;
        //the initial char in question for placement
        int p = 0;
        int r = startRow;
        int c = startCol;

        while (p < theWord.length()) {
            if (this.thePuzzle[startRow][startCol] == '-' || this.thePuzzle[startRow][startCol] == theWord.charAt(p)) {
                //This is the wrapping logic
                startRow = ((startRow + dx + getRows(this)) % getRows(this));
                startCol = ((startCol + dy + getCols(this)) % getCols(this));

                if (r == startRow && c == startCol) {
                    result = false;
                    break;
                }

                p++;
            } else {
                result = false;
                break;
            }
        }

        if (result == true) {
            place(theWord, r, c, dx, dy);
        }
        return result;
    }
    private void place(String theWord, int startRow, int startCol, int dx, int dy) {
        //the initial char in question for placement
        int p = 0;

        while (p < theWord.length()) {

            //********COMMENTED OUT DUE TO HANGING ISSUES**************
            thePuzzle[startRow][startCol] = (char) theWord.charAt(p);

            //This is the wrapping logic
            startRow = ((startRow + dx + getRows(this)) % getRows(this));
            startCol = ((startCol + dy + getCols(this)) % getCols(this));
            p++;
        }
    }

    protected void fillPuzzle() {
        for (int i = 0; i < _rows; i++) {
            for (int j = 0; j < _cols; j++) {
                if (thePuzzle[i][j] == '-') {

                    //randomly generate a capital char (65-90) for fill
                    Character aChar;
                    do {
                        aChar = (char) (random.nextInt(90) + 65);
                    } while ((int) aChar < 65 || (int) aChar > 90);

                    thePuzzle[i][j] = aChar;
                }
            }
        }
    }

    protected void printPuzzle(String puzzleName) {
        BufferedWriter out2 = null;
        try {
            //now add the array to the file created above
            out2 = new BufferedWriter(new FileWriter(puzzleName + ".pz", true));
            for (int i = 0; i < getRows(this); i++) {
                for (int j = 0; j < getCols(this); j++) {
                    out2.write(thePuzzle[i][j] + " ");
                }
                out2.write("\n");
            }
            out2.close();
        } catch (IOException e) {
            e.getMessage();
        }
    }

    public void loadPuzzletoGrid() {
        //fillPuzzle();
        for (int i = 0; i < 20; i++) {
            for (int j = 0; j < 20; j++) {
                WordSearchPuzzle.grid[i][j].setText((thePuzzle[i][j]).toString());
            }
        }

    }
}
Was it helpful?

Solution

This part of the code is currently causing the words to wrap when they hit the edge of the grid.

// This is the wrapping logic
startRow = ((startRow + dx + getRows(this)) % getRows(this));
startCol = ((startCol + dy + getCols(this)) % getCols(this));

if (r == startRow && c == startCol) {
  result = false;
  break;
}

Instead you want the move() method to fail when it reaches the edge with something like this:

startRow = startRow + dx;
startCol = startCol + dy;

if (startRow < 0 || startRow >= getRows(this) || startCol < 0 || startCol >= getCols(this)) {
  $result = false;
  break;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top