2

I am trying to create an evil hangman game using Java and TreeMaps. I'm trying to figure out how to put words into families. I have an ArrayList that is just a list of words and a String that represents a user input / guess. From this I have to create a map of patterns they generate and how many words match each pattern. In order to do this I need to break the word list up into different patterns and words based on the user guess.

For example, suppose I have a list:

{ALLY, BETA, COOL, DEAL, ELSE, FLEW, GOOD, HOPE, IBEX}

and User guesses an E.

Every word falls into one of a few families based on where the E is:

"----", is the pattern for [ALLY, COOL, GOOD]

"-E--", is the pattern for [BETA, DEAL]

"--E-", is the pattern for [FLEW, IBEX]

"E--E", is the pattern for [ELSE]

"---E", is the pattern for [HOPE]

I should also mention that the user also picks the length of the word he guessing so in this specific case it will consider only four letter words.

Is there a way to use a TreeMap object to help map out what words belong in what families? e.g.. to put it in the form TreeMap < String, ArrayList < String > >.

I am having a lot of trouble figuring this out so this is very incomplete but code so far is?

public class Hangman {


// instance vars
private ArrayList<String> list;
private boolean debugging;
private ArrayList<Character> guess;
private int numGuesses;
private String pattern;

// pre: words != null, words.size() > 0
// if debugOn = true, debuggin output is added
public HangmanManager(List<String> words, boolean debugOn) {
    list = new ArrayList<String>();
    debugging = debugOn;
    for(int i = 0; i < words.size(); i++){
        list.add(words.get(i));
    }
}

// pre: words != null, words.size() > 0
// debuggin output is not added
public HangmanManager(List<String> words) {
    list = new ArrayList<String>();
    for(int i = 0; i < words.size(); i++){
        list.add(words.get(i));
    }
}
public TreeMap<String, Integer> makeGuess(char guess) {
    if(alreadyGuessed(guess)){
        throw new IllegalStateException("Not valid imput.");
    }
    TreeMap<String, ArrayList<String>> newList = new TreeMap<String, ArrayList<String>>();

    newList.put(str, list);
    return null;
}
//helper method to generate an ArrayList that contains the letter that the user guesses
public ArrayList<String> getArrayList(char guess){
    String str = guess + "";
    ArrayList<String> newList = new ArrayList<String>();
    for(int i = 0; i < list.size(); i++){
        if(list.get(i).contains(str)){
            newList.add(list.get(i));
        }
    }
    return newList;
}

//helper method to break up the current word list into different patterns and words based on the user guess.
public TreeMap<String, ArrayList<String>> breakUp(char guess){
    Map<String, ArrayList<String>> newList = new TreeMap<String, ArrayList<String>>();
    String str = guess + "";
    newList.put(str, list);
    return null;
}

}

1 Answers1

3

You made good progress so far, please see the 2 methods below that'll help you fill in the cracks.

This method gets the pattern based on your guess and words like {ALLY, BETA, COOL, DEAL, ELSE, FLEW, GOOD, HOPE, IBEX}.

public String getPatternForWord(char guess, String word) {
    //regex to match all non-guess characters (ex: [^E] if guess was 'E')
    String replaceRegex = "[^" + guess + "]";

    //replace all non-guess characters with '-' (ex: replace all non-'E' with '-')
    String pattern = word.replaceAll(replaceRegex, "-");
    return pattern;
}

This method returns a map of patterns to their words Map<String, List<String>>.
For example: {----=[ALLY, COOL, GOOD], ---E=[HOPE], --E-=[FLEW, IBEX], -E--=[BETA, DEAL], E--E=[ELSE]}

public Map<String, List<String>> getPatternMapForGuess(char guess) {
    Map<String, List<String>> newMap = new TreeMap<String, List<String>>();

    for (String word : list) {
        String pattern = getPatternForWord(guess, word);

        //get the list of words for this pattern from map
        List<String> wordList;
        if (newMap.containsKey(pattern)) {
            wordList = newMap.get(pattern);
        } else {
            wordList = new ArrayList<String>();
        }

        //add word to list if it isn't there already
        if (!wordList.contains(word)) {
            wordList.add(word);
        }

        //pattern : word list
        newMap.put(pattern, wordList);
    }

    return newMap;
}

As an aside, I noticed that you always limit yourself to a specific implementation ArrayList<String> of List<String> instead of just the interface List<String>. It's good OOP practice to program to an interface not a specific implementation since it improves your flexibility.

For example:
List<String> newList = new ArrayList<String>();
instead of
ArrayList<String> newList = new ArrayList<String>();

and

Map<String, List<String>> newList = new TreeMap<String, List<String>>();
instead of
TreeMap<String, ArrayList<String>> newList = new TreeMap<String, ArrayList<String>>();

I won't go into details here, you can find out more with these links: 1, 2, 3.

Community
  • 1
  • 1