My mother-in-law likes a game in ipad. It is called Ruzzle Adventure. The idea is to find the word in a letter matrix. The longer the word is, the higher score you will have. For example, in the following letter arrays, you can find a ‘gates’ word.

Today, I think of cracking this game, find the potiential words it has.
The idea is to traverse each letter to its neighbor, go on and on, and see what word it can reach. And design a dictionary, get word from the dictionary.
I define some parameters to help.
puzzleCharArray[][], stores the characters of the puzzle game:
- public static char[][] puzzleCharArrzy = {
- {‘s’, ‘t’, ‘s’, ‘t’},
- {‘w’, ‘o’, ‘p’, ‘h’},
- {‘h’, ‘r’, ‘e’, ‘t’},
- {‘a’, ‘d’, ‘t’, ‘o’}
- };
stepHis[][], is to avoid duplicately visit to a puzzle letter. When I do backtrack, this stores what letters has already visited.
The most important is the dfs function. The boundary of it includes:
1. the (x,y) position should be within the array. i.e. can’t go to (-1,0)
2. The visited (x,y) shouldn’t be visited for 2nd time, which is helped by stepHis[][]
The return policies are:
If the current word is not found, then return.
If the current word is a prefix of a word, go on searching its neighbor.
If the current word is found in dictionary, add it to result list, and go on searching its neighbor.
The dfs code and comments are showed below:
- /*
- * Use dfs to find the possible word. Save the result in ArrayList result.
- * (x,y) indicate the current position in charPuzzle
- */
- public static void dfsWord(String word, int wordPos, int x, int y, boolean[][] stepHis, ArrayList result){
- if(x<0||x>=puzzleCharArrzy.length||y<0||y>=puzzleCharArrzy[0].length||stepHis[x][y]==true){
- return; //if (x,y) is in wrong position, or (x,y) is already traversed before, then return.
- }
- stepHis[x][y] = true; //mark this (x,y) as traversed.
- String currWord = word.substring(0, wordPos) + puzzleCharArrzy[x][y]; //update the current word
- int foundResult = searchWord(currWord); //find find in dictionary
- if(foundResult==NOT_FOUND){ //not found, then return
- stepHis[x][y] = false;
- return;
- }
- if(foundResult==WORD_FOUND&&wordPos!=0){
- result.add(currWord); //if found, then add to result list. Besides, it can go on finding the larger word
- }
- dfsWord(currWord, wordPos+1, x-1, y-1, stepHis, result);
- dfsWord(currWord, wordPos+1, x-1, y, stepHis, result);
- dfsWord(currWord, wordPos+1, x-1, y+1, stepHis, result);
- dfsWord(currWord, wordPos+1, x, y-1, stepHis, result);
- dfsWord(currWord, wordPos+1, x, y+1, stepHis, result);
- dfsWord(currWord, wordPos+1, x+1, y-1, stepHis, result);
- dfsWord(currWord, wordPos+1, x+1, y, stepHis, result);
- dfsWord(currWord, wordPos+1, x+1, y+1, stepHis, result);
- stepHis[x][y] = false; //unmark the step.
- }
Design the dictionary. Read the dictionary into a String[] array. Design a searchWord() function to check is a word is in the dictionary. The return result can be 3 types:
int WORD_FOUND=1, the word is in the dictionary.
int NOT_FOUNC=2, the word doesn’t exist in dictionary.
int PREFIX_FOUND=0, the word is a prefix of a certain word in the dictionary. For example, ‘appl’ is a prefix of ‘apple’.
I downloaded a txt file dictionary. It has alphebatic order. Load the dictionary to the String[].
The result is like below.
Input array:
public static char[][] puzzleCharArrzy = {
{‘s’, ‘t’, ‘s’, ‘t’},
{‘w’, ‘o’, ‘p’, ‘h’},
{‘h’, ‘r’, ‘e’, ‘t’},
{‘a’, ‘d’, ‘t’, ‘o’}
};
Output of top 10:
potsherd
sported
stored
sorted
stored
sorted
spored
whored
posher
ported
The complete code is here:
- package wordpuzzle;
- import java.io.BufferedReader;
- import java.io.FileReader;
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.Comparator;
- public class WordUtil {
- public static String[] dict;
- public static final int DICT_LENGTH = 109583; //the word length of the dictionary
- public static final String DICT_PATH = “C:/Users/lipeng/Work Space/WordPuzzle/wordsEn.txt”;
- public static final int PREFIX_FOUND = 0;
- public static final int WORD_FOUND = 1;
- public static final int NOT_FOUND = 2;
- public static final String puzzleChars = “hahalritudeanreutkdepdvit”;
- public static final int puzzleLen = 5;
- public static char[][] puzzleCharArrzy = {
- {‘s’, ‘t’, ‘s’, ‘t’},
- {‘w’, ‘o’, ‘p’, ‘h’},
- {‘h’, ‘r’, ‘e’, ‘t’},
- {‘a’, ‘d’, ‘t’, ‘o’}
- };
- public static void main(String[] args) {
- WordUtil.Init();
- ArrayList result = findWord();
- result = arraySort(result);
- printTop10(result);
- }
- /*
- * sort the result descend
- */
- public static ArrayList arraySort(ArrayList result){
- ArrayList returnResult = new ArrayList();
- while(!result.isEmpty()){
- int maxPos = -1;
- int maxLen = Integer.MIN_VALUE;
- String curr;
- for(int i=0;i < result.size();i++){
- curr = result.get(i);
- if(curr.length()>maxLen){
- maxLen = curr.length();
- maxPos = i;
- }
- }
- curr = result.remove(maxPos);
- returnResult.add(curr);
- }
- return returnResult;
- }
- public static void printResult(ArrayList result){
- for(int i=0;i < result.size();i++){
- System.out.println(result.get(i));
- }
- }
- /*
- * print the top 10 result
- */
- public static void printTop10(ArrayList result){
- for(int i=0;i
- System.out.println(result.get(i));
- }
- }
- /*
- * traverse all the position, try to find the word.
- * Use stepHis to record if a position has been traversed before.
- */
- public static ArrayList findWord(){
- boolean[][] stepHis = new boolean[puzzleCharArrzy.length][puzzleCharArrzy[0].length];
- ArrayList result = new ArrayList();
- for(int i=0;i < puzzleCharArrzy.length;i++){
- for(int j=0;j < puzzleCharArrzy[0].length;j++){
- dfsWord(“”, 0, i, j, stepHis, result);
- }
- }
- return result;
- }
- /*
- * Use dfs to find the possible word. Save the result in ArrayList result.
- * (x,y) indicate the current position in charPuzzle
- */
- public static void dfsWord(String word, int wordPos, int x, int y, boolean[][] stepHis, ArrayList result){
- if(x<0||x>=puzzleCharArrzy.length||y<0||y>=puzzleCharArrzy[0].length||stepHis[x][y]==true){
- return; //if (x,y) is in wrong position, or (x,y) is already traversed before, then return.
- }
- stepHis[x][y] = true; //mark this (x,y) as traversed.
- String currWord = word.substring(0, wordPos) + puzzleCharArrzy[x][y]; //update the current word
- int foundResult = searchWord(currWord); //find find in dictionary
- if(foundResult==NOT_FOUND){ //not found, then return
- stepHis[x][y] = false;
- return;
- }
- if(foundResult==WORD_FOUND&&wordPos!=0){
- result.add(currWord); //if found, then add to result list. Besides, it can go on finding the larger word
- }
- dfsWord(currWord, wordPos+1, x-1, y-1, stepHis, result);
- dfsWord(currWord, wordPos+1, x-1, y, stepHis, result);
- dfsWord(currWord, wordPos+1, x-1, y+1, stepHis, result);
- dfsWord(currWord, wordPos+1, x, y-1, stepHis, result);
- dfsWord(currWord, wordPos+1, x, y+1, stepHis, result);
- dfsWord(currWord, wordPos+1, x+1, y-1, stepHis, result);
- dfsWord(currWord, wordPos+1, x+1, y, stepHis, result);
- dfsWord(currWord, wordPos+1, x+1, y+1, stepHis, result);
- stepHis[x][y] = false; //unmark the step.
- }
- public static int searchWord(String word){
- return binarySearch(word, 0, DICT_LENGTH-1);
- }
- /*
- * use binarysearch to find the word in the dict.
- */
- public static int binarySearch(String word, int start, int end){
- if(start>end){ //time to result result
- if(dict[start].length()>=word.length()&&dict[start].subSequence(0, word.length()).equals(word)){
- return PREFIX_FOUND; //the word is a part of word in dict. it can still go on searching
- }
- if(dict[end].length()>=word.length()&&dict[end].subSequence(0, word.length()).equals(word)){
- return PREFIX_FOUND; //the word is a part of word in dict. it can still go on searching
- }
- return NOT_FOUND;
- }
- int mid = (start+end)/2;
- int cmp = dict[mid].compareTo(word);
- if(cmp<0){
- return binarySearch(word, mid+1, end);
- }
- else if(cmp>0){
- return binarySearch(word, start, mid-1);
- }
- else{
- return WORD_FOUND;
- }
- }
- public static void Init(){
- dict = readFile(DICT_PATH);
- }
- /*
- * to initial the puzzleChar by inputting a string.
- */
- public static void Init2(){
- puzzleCharArrzy = new char[puzzleLen][puzzleLen];
- for(int i=0;i< puzzleLen;i++){
- for(int j=0;j < puzzleLen;j++){
- puzzleCharArrzy[i][j] = puzzleChars.charAt(puzzleLen*i+j);
- }
- }
- dict = readFile(DICT_PATH);
- }
- /*
- * read the dict file from dict.txt
- */
- public static String[] readFile(String file){
- String[] dict = new String[DICT_LENGTH];
- try{
- BufferedReader br = new BufferedReader(new FileReader(file));
- String line;
- int i=0;
- while ((line = br.readLine()) != null) {
- dict[i] = line;
- i++;
- }
- br.close();
- }catch(Exception e){
- e.printStackTrace();
- }
- return dict;
- }
- }
download the dictionary here: link