For a homework assignment I have to create a program that will cheat at hangman. In order to do this I need to come up with a way of grouping words into families via the words letter locations. So for instance if the word length is 4 and they guess "e" all words that go "- - - e " will be in one of the hashmap's Arraylists with that pattern as a key and all the words that that go "- e - -" will be in another of the same hashmap's ArrayLists with the pattern as a key. My problem is that despite my program being able to identify the pattern. It still returns an empty set or one ArrayList containing all the words. I have been trying different things for over an hour now and I can't seem to get them to group correctly. Any help is greatly appreciated. Here is the code I have for the class that separates the words and adds them to the Hashmap.
import java.util.ArrayList;
import java.lang.StringBuilder;
import java.util.HashMap;
public class EvilEngine
{
HashMap<StringBuilder, ArrayList> families = new HashMap<StringBuilder, ArrayList>();
int k = 0;
ArrayList<String> currentList = new ArrayList();
StringBuilder blankPattern = new StringBuilder("");
StringBuilder newPattern = new StringBuilder("");
public void PatternMatcher(ArrayList wordlist, char guess, Integer wordlength)
{
String word;
int j = 0;
int x = 0;
int biggest = 0;
StringBuilder longest = null;
while(x < wordlist.size())
{
int i = 0;
int index = 0;
for (i=0; i < wordlength; i++)
{
blankPattern = blankPattern.append("-");
}
boolean boo = false;
newPattern = blankPattern;
word = (String) wordlist.get(x);
index = word.indexOf(guess);
while (index >= 0)
{
blankPattern.setCharAt(index, guess);
newPattern = blankPattern;
index = word.indexOf(guess, index + 1);
}
this.PatternCompiler(word,newPattern);
blankPattern = blankPattern.delete(0,wordlength);
x++;
}
}
public void PatternCompiler (String word, StringBuilder pattern)
{
if(!families.containsKey(pattern))
{
ArrayList<String> newPatternList = new ArrayList();
newPatternList.add(word);
families.put(pattern, newPatternList);
}
if (families.containsKey(pattern))
{
ArrayList<String> oldPatternList = new ArrayList();
oldPatternList = families.get(pattern);
oldPatternList.add(word);
families.put(pattern, oldPatternList);
}
else {
System.out.println("Error");
}
}
public HashMap<StringBuilder, ArrayList> returnFamilies (){
return families;
}
}
While there are several more-or-less minor issues with your code, I suspect the main problem is that your HashMap
has keys of type StringBuilder
instead of String
. HashMap
uses the hashCode()
function of the key object to determine if it is already in the map or not. For a StringBuilder
, the hash value is probably just going to be the address of the object (using the implementation inherited from the Object
class).
Since newPattern
is a class-level variable whose scope is outside of the functions, when you pass it to the PatternCompiler()
function, the parameter pattern
there is just a reference to the same class-level object (ie, will have the same hash code). And this object (nor its hash code) never changes in your code because blankPattern
is also declared at the class level and, while you change the value of blankPattern
, you never change the object it refers to. So re-assigning it to newPattern
each time through your while
loop does not change anything (and is basically clutter).
To fix that, you will want to make the key type of your HashMap
be String
instead of StringBuilder
. The String
class defines a hashCode()
function that will return different codes depending on the actual contents of the string (instead of just the address of the object like StringBuilder
). (Also, as indicated, there is no reason for blankPattern
to be declared at the class level instead of just inside your PatternMatcher()
function, and you don't need newPattern
at all.)
While that was the main issue with your code, another pretty big issue has to do with the second if
condition in your PatternCompiler()
function. In the previous if
block you add a new ArrayList to families if there isn't already one for the pattern. So no matter what, the second if
conditional ( if (families.containsKey(pattern))
) will be true at that point. Because both blocks add word
to the list for families
, there is the potential that some words will be added twice.
Good luck!
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.