简体   繁体   中英

How to split a 2D array in different sized pieces for a crossword?

I am experimenting with a generator for a crossword puzzle but I am getting stuck when it is time to split it up into different pieces. I have a 2D array where I store the crossword like this:

int SIZE = 10; //This can be higher for bigger crosswords
Character[][] crossword = new Character[SIZE][SIZE];

I then add a few words to this crossword and for example end up with the following array (. = empty square):

..........
..........
..C...H...
..A...O...
..TIGER...
......S...
...DOVE...
..........
..........
..........

How do I split this 2D array so that I end up with pieces that contains at least 2 letters but not a whole word. The letters must also be next to each other horizontally or vertically but not diagonally. For example I could end up with the following pieces:

C    TIG    H    ER    DOV
A           O     S
                  E

The following piece is NOT valid because the letters is not horizontally or vertically next to eachother.

  O
GE
  S

My first atempt to split this up was by doing the following:

int chunksize = 2; //This should vary depending on how big the pieces should be
List<Character[][]> subArrays = new ArrayList<>();
for(int i = 0; i < SIZE; i += chunksize){
    for(int j = 0; j < SIZE; j += chunksize){
        Character[][] sub = new Character[chunksize][chunksize];
        sub[0][0] = crossword[i][j];
        sub[0][1] = crossword[i][j + 1];
        sub[1][0] = crossword[i + 1][j];
        sub[1][1] = crossword[i + 1][j + 1];
        if(sub[0][0] != null || sub[0][1] != null || sub[1][0] != null || sub[1][1] != null){
            subArrays.add(sub);
        }
    }
}

However, this might create pieces that contains only one letter or pieces where the letters is not next to each other. I do not know how I should solve this problem which is why I come here for help.

Domino packing

The following approach creates as many size-2 blocks as possible. Afterwards, any remaining individual letters need to be attached to a neighbouring block somehow -- eg, by picking one of the neighbouring blocks at random.

Create a graph with a vertex for each position occupied by a letter, and an edge between any pair of vertically or horizontally adjacent letter positions. Now compute a maximum matching on this graph: this chooses a maximum-size edge subset such that no vertex is incident on more than one edge. These edges correspond to the size-2 blocks.

If you imagine the grid as a chessboard, you'll notice that every square is either white or black, and no edge connects two white cells or two black cells: this means that the graph is bipartite, which in turn means that you can use the O(|E|*sqrt(|V|))-time Hopcroft-Karp algorithm , which is faster and simpler than Edmonds's algorithm for general graphs.

What I would suggest you do is to convert each row and each column into a String of it's own.

eg: First 3 Rows

..........
..........
..C...H...

First 3 columns

..........
..........
..CAT.....

You could do this by using for loops for example:

for(int x = 0; x < SIZE; x++){
    //Loop through rows and columns.
    //(eg:crossword[x][y] in this loop will extract a row of values)
    //(eg:crossword[y][x] in this loop will extract a column of values)
    for(int y = 0; y < SIZE; y++){
        //Code to build each row/column string
    }
    //Add extracted Strings to an ArrayList?
}

After you have these string you could split them by using: (Assuming . is still your deliminator)

s.split("\\.");

This will leave you with Arrays of the string from each row and columns

Extracts C and H as separate Strings from

..........
..........
..C...H...

Extracts CAT as a single String from

..........
..........
..CAT.....

This should allow you to check their length against chunksize and return the combinations you want.

Hopefully I have understood the problem correctly or it has at least given you some ideas that could be used to develop the solution you're looking for.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM