FourInARow/AAPLBoard.m
/* |
Copyright (C) 2015 Apple Inc. All Rights Reserved. |
See LICENSE.txt for this sample’s licensing information |
Abstract: |
Basic class representing the Four-In-A-Row game board. |
*/ |
#import "AAPLBoard.h" |
const static NSInteger AAPLBoardWidth = 7; |
const static NSInteger AAPLBoardHeight = 6; |
@implementation AAPLBoard { |
AAPLChip _cells[AAPLBoardWidth * AAPLBoardHeight]; |
} |
+ (NSInteger)width { |
return AAPLBoardWidth; |
} |
+ (NSInteger)height { |
return AAPLBoardHeight; |
} |
- (instancetype)init { |
self = [super init]; |
if (self) { |
_currentPlayer = [AAPLPlayer redPlayer]; |
} |
return self; |
} |
- (void)updateChipsFromBoard:(AAPLBoard *)otherBoard { |
memcpy(_cells, otherBoard->_cells, sizeof(_cells)); |
} |
- (AAPLChip)chipInColumn:(NSInteger)column row:(NSInteger)row { |
return _cells[row + column * AAPLBoardHeight]; |
} |
- (void)setChip:(AAPLChip)chip inColumn:(NSInteger)column row:(NSInteger)row { |
_cells[row + column * AAPLBoardHeight] = chip; |
} |
- (NSString *)debugDescription { |
NSMutableString *output = [NSMutableString string]; |
for (NSInteger row = AAPLBoardHeight - 1; row >= 0; row--) { |
for (NSInteger column = 0; column < AAPLBoardWidth; column++) { |
AAPLChip chip = [self chipInColumn:column row:row]; |
NSString *playerDescription = [AAPLPlayer playerForChip:chip].debugDescription ?: @" "; |
[output appendString:playerDescription]; |
NSString *cellDescription = (column + 1 < AAPLBoardWidth) ? @"." : @""; |
[output appendString:cellDescription]; |
} |
[output appendString:((row > 0) ? @"\n" : @"")]; |
} |
return output; |
} |
- (NSInteger)nextEmptySlotInColumn:(NSInteger)column { |
for (NSInteger row = 0; row < AAPLBoardHeight; row++) { |
if ([self chipInColumn:column row:row] == AAPLChipNone) { |
return row; |
} |
} |
return -1; |
} |
- (BOOL)canMoveInColumn:(NSInteger)column { |
return [self nextEmptySlotInColumn:column] >= 0; |
} |
- (void)addChip:(AAPLChip)chip inColumn:(NSInteger)column { |
NSInteger row = [self nextEmptySlotInColumn:column]; |
if (row >= 0) { |
[self setChip:chip inColumn:column row:row]; |
} |
} |
- (BOOL)isFull { |
for (NSInteger column = 0; column < AAPLBoardWidth; column++) { |
if ([self canMoveInColumn:column]) { |
return NO; |
} |
} |
return YES; |
} |
- (NSArray<NSNumber *> *)runCountsForPlayer:(AAPLPlayer *)player { |
AAPLChip chip = player.chip; |
NSMutableArray<NSNumber *> *counts = [NSMutableArray array]; |
// Detect horizontal runs. |
for (NSInteger row = 0; row < AAPLBoardHeight; row++) { |
NSInteger runCount = 0; |
for (NSInteger column = 0; column < AAPLBoardWidth; column++) { |
if ([self chipInColumn:column row:row] == chip) { |
++runCount; |
} |
else { |
// Run isn't continuing, note it and reset counter. |
if (runCount > 0) { |
[counts addObject:@(runCount)]; |
} |
runCount = 0; |
} |
} |
if (runCount > 0) { |
// Note the run if still on one at the end of the row. |
[counts addObject:@(runCount)]; |
} |
} |
// Detect vertical runs. |
for (NSInteger column = 0; column < AAPLBoardWidth; column++) { |
NSInteger runCount = 0; |
for (NSInteger row = 0; row < AAPLBoardHeight; row++) { |
if ([self chipInColumn:column row:row] == chip) { |
++runCount; |
} |
else { |
// Run isn't continuing, note it and reset counter. |
if (runCount > 0) { |
[counts addObject:@(runCount)]; |
} |
runCount = 0; |
} |
} |
if (runCount > 0) { |
// Note the run if still on one at the end of the column. |
[counts addObject:@(runCount)]; |
} |
} |
// Detect diagonal (northeast) runs |
for (NSInteger startColumn = -AAPLBoardHeight; startColumn < AAPLBoardWidth; startColumn++) { |
// Start from off the edge of the board to catch all the diagonal lines through it. |
NSInteger runCount = 0; |
for (NSInteger offset = 0; offset < AAPLBoardHeight; offset++) { |
NSInteger column = startColumn + offset; |
if (column < 0 || column > AAPLBoardWidth) { |
continue; // Ignore areas that aren't on the board. |
} |
if ([self chipInColumn:column row:offset] == chip) { |
++runCount; |
} |
else { |
// Run isn't continuing, note it and reset counter. |
if (runCount > 0) { |
[counts addObject:@(runCount)]; |
} |
runCount = 0; |
} |
} |
if (runCount > 0) { |
// Note the run if still on one at the end of the line. |
[counts addObject:@(runCount)]; |
} |
} |
// Detect diagonal (northwest) runs |
for (NSInteger startColumn = 0; startColumn < AAPLBoardWidth + AAPLBoardHeight; startColumn++) { |
// Iterate through areas off the edge of the board to catch all the diagonal lines through it. |
NSInteger runCount = 0; |
for (NSInteger offset = 0; offset < AAPLBoardHeight; offset++) { |
NSInteger column = startColumn - offset; |
if (column < 0 || column > AAPLBoardWidth) { |
continue; // Ignore areas that aren't on the board. |
} |
if ([self chipInColumn:column row:offset] == chip) { |
++runCount; |
} |
else { |
// Run isn't continuing, note it and reset counter. |
if (runCount > 0) { |
[counts addObject:@(runCount)]; |
} |
runCount = 0; |
} |
} |
if (runCount > 0) { |
// Note the run if still on one at the end of the line. |
[counts addObject:@(runCount)]; |
} |
} |
return counts; |
} |
@end |
Copyright © 2015 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2015-09-16