Monthly Archives: August 2013

iOS Scrabble Word Detection

A few months back I was working on a prototype for a word game. Part of that game was writing a word detection algorithm. Most games handle this by creating a local database of all the word their game accepts. That way they can cross reference the word and control what their game considers acceptable. Getting that list however isn’t a simple task. Since the game was in beta, I decided to leverage the native dictionary for my detection. Also not a simple task but quicker to implement.

To start we need to have our function detect if a word is valid.

-(bool)isRealWord:(NSString *)currentWord{
    
    bool isValid = false;
    
    UITextChecker* checker = [[UITextChecker alloc] init];
    NSRange range;
    
    range = [checker rangeOfMisspelledWordInString:currentWord range:NSMakeRange(0, [currentWord length]) startingAt:0 wrap:NO language:@"en_US"];
    
    if (range.location == NSNotFound) {
        isValid = true; 
    }
    return isValid;
}

The core of the functionality is on the highlighted line, which sets the range for misspelling. The easiest way to detect if a word is real is to cross check for misspellings. By checking the word against this we know that the word is a real word. A fairly simple check that gets us the first part of the information we require to detect a word.

The second part of the equation is to know if the word is a valid scrabble word. For example, a persons name is not a word. This gets a bit more complex, since some words have multiple meetings. The solution to this, at its core, is to use the word in a sentence and detect what type of word it is.

-(bool)isAllowedWordType:(NSString *)currentWord{
    
    __block bool isAllowedWordTypeValid = true;
    NSString * currentWordUpperCaseFirstLetter =  [currentWord stringByReplacingCharactersInRange:NSMakeRange(0,1) withString:[[currentWord substringToIndex:1] uppercaseString]];
    
    NSString *str = [NSString stringWithFormat: @"the %@ is ", currentWordUpperCaseFirstLetter];
    
    NSLinguisticTagger *tagger = [[NSLinguisticTagger alloc] initWithTagSchemes:[NSArray arrayWithObject:NSLinguisticTagSchemeNameTypeOrLexicalClass] options:~NSLinguisticTaggerOmitWords];
    
    [tagger setString:str];
    
    [tagger enumerateTagsInRange:NSMakeRange(0, [str length]) scheme:NSLinguisticTagSchemeNameTypeOrLexicalClass options:~NSLinguisticTaggerOmitWords usingBlock:^(NSString *tag, NSRange tokenRange, NSRange sentenceRange, BOOL *stop) {
        
        if([tag isEqualToString:@"OtherWord"] || [tag isEqualToString:@"PersonalName"])   {
            isAllowedWordTypeValid = false;
        }
        
    }];
    
    return isAllowedWordTypeValid;
}

First we set the word to have a capitol letter as the first character of the word. This is important in the detection of the difference later in the function for “PersonalName”. We then put that word in the string “the (word) is”. This sentence fragment puts context around what we are trying to detect to help our code better understand the scrabble logic around playable words. We then create a NSLinguisticsTagger and set the String we created. The code then analysis that string to extract the type of tag that is associated with our word. There are many different types of tags, however for our scrabble word detection, we’re primarily interested in “OtherWord” and “PersonalName” as these are the failure points for the sentence.

When we apply these two functions together we can determine if a word is valid. It took some time to figure out this method of detection, but its still a lot less time then building and managing a database. I still recommend the database solution to ensure perfection, however if you’re looking to make a quick proof of concept this is a great start.

You can find a working example of this approach on my Github. Word Detection Example Project Happy prototyping!