Fun question:
In this particular case, I agree with Luke about subclassing the UIButton. This way you could give each button an (X, Y) on your grid, as well as a (Xnext, Ynext) list for all of the possible expected next press locations (if the button itself can be used to make multiple words). Externally you will compare the currently being hit against the expected (Xnext, Ynext). If the two dont match, this is the signal you are looking for.
This is an answer that accounts for all of your situations, forward and backward horizontal (if you choose to implement backware), upward and downward vertical (if you choose to implement upward), and any diagonal, or any other combination you can come up with!
This also accounts for lets say hitting the D, then the O then trying to press the D again versus hitting the G. It also takes care of hitting the incorrect G.
Create a new .m .h pair of files (a new object) and give it your name.
Some example code for implementing a custom UIButton (h file):
@interface myConnectedUIButton : UIButton {
BOOL isAWordBeginCharacter;
unsigned int beginWordKey;
unsigned int myGridX;
unsigned int myGridY;
NSMutableArray * myConnectedSet;
}
-(id)init;
-(void)initWithGridX:(unsigned int)X GridY:(unsigned int)Y BeginChar:(BOOL)yesNo BeginWordKey:(unsigned int)key;
-(void)setGridPosWithX:(unsigned int)X Y:(unsigned int)Y;
-(void)setGridX:(unsigned int)X;
-(void)setGridY:(unsigned int)Y;
-(unsigned int)getGridX;
-(unsigned int)getGridY;
-(void)setIsABeginChar:(BOOL)yesNo;
-(BOOL)getIsABeginChar;
-(void)addPosToConnectedSetGridX:(unsigned int)X GridY:(unsigned int)Y WordKey:(unsigned int)key;
-(NSArray *)getMyConnectedSetArray;
-(void)clearConnectedSet;
@end
In the .m file of your
@implementation myConnectedUIButton
-(id)init{
[super init];
// Lets go ahead and initialize the NSMutableArray here also IFF it hasnt already been allocated
if( nil == myConnectedSet ){
myConnectedSet = [[NSMutableArray alloc] init];
}
// Lets also zero out the x, y position
myGridX = 0;
myGridY = 0;
// Lets also state that this is NOT a begin char for the time being and 0 for the begin char key
isAWordBeginCharacter = NO;
beginWordKey = 0;
return self;
}
-(void)initWithGridX:(unsigned int)X GridY:(unsigned int)Y BeginChar:(BOOL)yesNo BeginWordKey:(unsigned int)key{
// Lets go ahead and initialize the NSMutableArray here also IFF it hasnt already been allocated
if( nil == myConnectedSet ){
myConnectedSet = [[NSMutableArray alloc] init];
}
myGridX = X;
myGridY = Y;
isAWordBeginCharacter = yesNo;
beginWordKey = key;
}
-(void)setGridPosWithX:(unsigned int)X Y:(unsigned int)Y{
myGridX = X;
myGridY = Y;
}
-(void)setGridX:(unsigned int)X{
myGridX = X;
}
-(void)setGridY:(unsigned int)Y{
myGridY = Y;
}
-(unsigned int)getGridX{
return myGridX;
}
-(unsigned int)getGridY{
return myGridY;
}
-(void)setIsABeginChar:(BOOL)yesNo{
isAWordBeginCharacter = yesNo;
}
-(BOOL)getIsABeginChar{
return isAWordBeginCharacter;
}
-(void)addPosToConnectedSetGridX:(unsigned int)X GridY:(unsigned int)Y WordKey:(unsigned int)key{
[myConnectedSet addObject:[GridPointNext GridPointNextWithX:X GridPointY:Y NextWordKey:key]];
}
-(NSArray *)getMyConnectedSetArray{
return myConnectedSet;
}
-(void)clearConnectedSet{
[myConnectedSet removeAllObjects];
}
-(void)dealloc{
[myConnectedSet release];
[super dealloc];
}
@end
You will also now need a "GridPointNext" object.
The Grid Object header should look as follows:
@interface GridPointNext : NSObject {
unsigned int GridPointX;
unsigned int GridPointY;
unsigned int nextWordKey;
}
+(GridPointNext *)GridPointNextWithX:(unsigned int)X GridPointY:(unsigned int)Y NextWordKey:(unsigned int)key;
-(id)initWithX:(unsigned int)X GridPointY:(unsigned int)Y NextWordKey:(unsigned int)key;
-(unsigned int)getGridX;
-(unsigned int)getGridY;
-(unsigned int)getNextWordKey;
@end
The m file for the object should look as follows:
@implementation GridPointNext
+(GridPointNext *)GridPointNextWithX:(unsigned int)X GridPointY:(unsigned int)Y NextWordKey:(unsigned int)key{
GridPointNext * aPoint = [[GridPointNext alloc] initWithX:X GridPointY:Y NextWordKey:key];
[aPoint autorelease];
return aPoint;
}
-(id)initWithX:(unsigned int)X GridPointY:(unsigned int)Y NextWordKey:(unsigned int)key{
GridPointX = X;
GridPointY = Y;
nextWordKey = key;
return self;
}
-(unsigned int)getGridX{
return GridPointX;
}
-(unsigned int)getGridY{
return GridPointY;
}
-(unsigned int)getNextWordKey{
return nextWordKey;
}
@end
You will have to deal with the dealloc portion. This at least give you some tools for creating your custom button and your word list algorithm around it.