patternMinor
Board Evaluator for Bejeweled Clone
Viewed 0 times
bejeweledevaluatorforcloneboard
Problem
I've been prototyping a Match 3 game (Bejeweled clone) because I have an interesting concept for one, and because it is good practice. One key aspect of my version is that the matches must contain one of the swapped orbs. Therefore matches elsewhere on the board do not get destroyed (and for now there are no combos).
To solve this, I devised a special algorithm that searches for matches starting with the positions of the swapped orbs.
Since this is a naive implementation of Match 3, I am sure that there are lots of problems with the code and especially with the algorithm.
Here is the initial evaluation that happens when a player tries to swap two orbs:
And here is the board evaluator class. It is possible that all of this class should simply be in the
DMBoardEval.h
```
#import
#import "DMGameBoard.h"
@interface DMBoardEval : NSObject
@property (nonatomic) DMGameBoard *board;
-(BOOL) swapHasMatchesForOrb:(DMOrb )firstOrb withOrb:(DMOrb )secondOrb;
-(void) resolveSwapBetweenPosition:(C
To solve this, I devised a special algorithm that searches for matches starting with the positions of the swapped orbs.
Since this is a naive implementation of Match 3, I am sure that there are lots of problems with the code and especially with the algorithm.
Here is the initial evaluation that happens when a player tries to swap two orbs:
-(BOOL) swapOrb:(DMOrb *)firstOrb withOrb:(DMOrb *)secondOrb {
//if its the same orb, fail
if ([firstOrb isEqual:secondOrb]) {
return NO;
}
//check and make sure that the orbs are next to each other
if (![self orbAdjacent:firstOrb toOrb:secondOrb]) {
return NO;
}
//potentially check and make sure they are not the same color here
//makes a copy of the board inside the eval class
_boardEval.board = self.board;
//actually moves the pieces, but will only save the new board if there is a match
if ([_boardEval swapHasMatchesForOrb:firstOrb withOrb:secondOrb]) {
[_boardEval resolveSwapBetweenPosition:firstOrb.boardPosition position:secondOrb.boardPosition];
self.board = _boardEval.board;
return YES;
}
return NO;
}And here is the board evaluator class. It is possible that all of this class should simply be in the
GameBoard class, but I am unsure. Right now the Game class has both the GameBoard and the BoardEvaluator, and processes the moves of the game sent by the UI.DMBoardEval.h
```
#import
#import "DMGameBoard.h"
@interface DMBoardEval : NSObject
@property (nonatomic) DMGameBoard *board;
-(BOOL) swapHasMatchesForOrb:(DMOrb )firstOrb withOrb:(DMOrb )secondOrb;
-(void) resolveSwapBetweenPosition:(C
Solution
This can be 100% eliminated:
And instead, change the property declaration to look like this:
I'd rewrite this method:
As this (notice I'm also renaming... "find matches" implies we'll return matches):
This is just a subsection of one of your methods, but it's a little confusing. Let' see if we can clear it up and make it a little more efficient.
This pattern can be applied in 3 other places. This pattern eliminates the
-(void) setBoard:(DMGameBoard *)board {
_board = [DMGameBoard boardWithBoard:board];
}And instead, change the property declaration to look like this:
@property (copy) DMGameBoard *board;I'd rewrite this method:
-(BOOL) findMatchesForOrb:(DMOrb *)orb {
if ([self searchRowForMatchesWithOrb:orb]) {
return YES;
}
if ([self searchColumnForMatchesWithOrb:orb]) {
return YES;
}
return NO;
}As this (notice I'm also renaming... "find matches" implies we'll return matches):
- (BOOL)hasMatchesForOrb:(DMOrb *)orb {
return [self searchRowForMatchesWithOrb:orb] ||
[self searchColumnForMatchesWithOrb:orb];
}for (int i = orb.boardPosition.x; i = 3) {
return YES;
}This is just a subsection of one of your methods, but it's a little confusing. Let' see if we can clear it up and make it a little more efficient.
for (int i = orb.boardPosition.x; i = 3) {
return YES;
}
} else {
break;
}
}This pattern can be applied in 3 other places. This pattern eliminates the
otherColorFound variable and saves us a lot of iterations. Consider if your row is say 20 orbs wide, and I move an orb into the 20th spot. Your original implementation will iterate 20 times no matter what. With this implementation, we stop as soon as we find a different .type or as soon as we find 3 in a row.Code Snippets
-(void) setBoard:(DMGameBoard *)board {
_board = [DMGameBoard boardWithBoard:board];
}@property (copy) DMGameBoard *board;-(BOOL) findMatchesForOrb:(DMOrb *)orb {
if ([self searchRowForMatchesWithOrb:orb]) {
return YES;
}
if ([self searchColumnForMatchesWithOrb:orb]) {
return YES;
}
return NO;
}- (BOOL)hasMatchesForOrb:(DMOrb *)orb {
return [self searchRowForMatchesWithOrb:orb] ||
[self searchColumnForMatchesWithOrb:orb];
}for (int i = orb.boardPosition.x; i < kNumOrbsPerRow; i++) {
if (!otherColorFound) {
if (orb.type == ((DMOrb *)row.orbs[i]).type) {
numberOfOrbs++;
} else {
otherColorFound = YES;
}
}
}
if (numberOfOrbs >= 3) {
return YES;
}Context
StackExchange Code Review Q#74221, answer score: 8
Revisions (0)
No revisions yet.