/** * fillPuzzle() * * <p>Our recursive backtracking algorithm for solving the crossword puzzle. For each slot in the * slots array, tries to find an UNUSED word from the words array that fits. If no such word is * found, or all the words it's tried lead to backtracks, returns false to backtrack to the * previous call and tell it to choose a different word. If we've filled every slot, we print the * solution and return true, which causes every other call to also return true, bringing us back * to the solve() wrapper method. */ private boolean fillPuzzle(int slot) { // If we've filled every slot, slot will be equal to // the length of the slots array. In that case, we are // done, so we print the solution and return true to // tell all the previous calls to also return true: System.out.println("fillpuzzle"); if (slot == slots.length) { printPuzzle(); return true; } // Consider each word from the words array as a potential // fit for the current slot: for (CrosswordWord word : words) { System.out.println("in for loop of fillpuzzle:::" + word.getWord()); // words[i].printWord(); // If the word is UNUSED and fits in the slot given // its length and the letters already there from other // words, we place the word in the slot (marking it // USED in the process), and make a recursive call to // fill the next slot. If that call backtracks (returns // false), we remove the word from the slot and choose // a different one: if (wordFitsInSlot(word, slots[slot])) { System.out.println("If the word fits:::" + word.getWord()); putWordInSlot(word, slots[slot]); System.out.println("After putting the word::::" + word.getWord()); if (fillPuzzle(slot + 1)) { return true; } removeWordFromSlot(word, slots[slot]); } } // If we get here, we've tried every word in the words // array for this slot, and all have either not fit or // lead to backtracks, so we need to backtrack as well by // returning false to tell the previous call to choose a // different word: numBacktracks++; return false; }
/** * putWordInSlot() * * <p>Puts each letter from the word it's passed into the slot it's passed, and marks the word * USED. Also increments the positions in the letterUsage array corresponding to the slot to * indicate that one more word is now using these letters. */ private void putWordInSlot(CrosswordWord w, CrosswordSpace slot) { Point position = new Point(slot.getStart()); for (int i = 0; i < slot.getLength(); i++) { // Put each letter from the word into this slot of // the puzzle: puzzle[position.x][position.y] = w.getWord().charAt(i); // Record the fact that one more word is now using the // letter at this position: letterUsage[position.x][position.y]++; // Advance to the next position in the slot: position.x += slot.getDirection().x; position.y += slot.getDirection().y; } // Mark the word as USED: w.setUsed(true); }
/** * wordFitsInSlot() * * <p>Returns true if the word passed to it fits into the slot passed to it AND is unused, * otherwise returns false. */ private boolean wordFitsInSlot(CrosswordWord w, CrosswordSpace slot) { // If the length of the word doesn't match the length of the // slot, or the word is already used, we can't put this word // here and so we return false: if (w.getWord().length() != slot.getLength() || w.isUsed()) { return false; } // Otherwise we examine each position in the slot. If // there are letters in the slot already, and those letters // DON'T match the letters at the corresponding positions // in our word, the word won't fit and we return false: Point position = new Point(slot.getStart()); for (int i = 0; i < slot.getLength(); i++) { if (puzzle[position.x][position.y] != BLANK && puzzle[position.x][position.y] != w.getWord().charAt(i)) { return false; } // Advance to the next position in the slot: position.x += slot.getDirection().x; position.y += slot.getDirection().y; } // If we get here, it means the word is unused, the right // length for the current slot, and its letters match any // letters already in the slot: return true; }