TicTacToe/AAPLTicTacToeViewController.m
/* |
Copyright (C) 2016 Apple Inc. All Rights Reserved. |
See LICENSE.txt for this sample’s licensing information |
Abstract: |
View controller for a tic-tac-toe game demonstrating accessible custom controls using the accessibility methods of NSControl subclasses, accessibility protocols, and NSAccessibilityElement. |
*/ |
#import "AAPLTicTacToeViewController.h" |
#import "AAPLTicTacToeAIEngine.h" |
#import "AAPLTicTacToeBoard.h" |
static const NSInteger AAPLMaxDifficulty = 10; |
static const NSInteger AAPLMinDifficulty = 0; |
@interface AAPLTicTacToeViewController () |
@property (nonatomic, strong) AAPLTicTacToeGame *game; |
@property (nonatomic, strong) AAPLTicTacToeAIEngine *ai; |
@end |
@implementation AAPLTicTacToeViewController |
- (void)awakeFromNib |
{ |
if ( self.game == nil ) |
{ |
self.game = [AAPLTicTacToeGame new]; |
} |
self.boardView.game = self.game; |
self.ai = [AAPLTicTacToeAIEngine new]; |
self.resetGameButton.delegate = self; |
self.boardView.delegate = self; |
self.playAICheckbox.delegate = self; |
[self refresh]; |
} |
- (void)refresh |
{ |
[self.boardView setNeedsDisplay:YES]; |
switch ( self.game.state ) |
{ |
case AAPLTicTacToeGameStateXTurn: |
self.statusText.stringValue = NSLocalizedString(@"X's turn", nil); |
break; |
case AAPLTicTacToeGameStateOTurn: |
self.statusText.stringValue = NSLocalizedString(@"O's turn", nil); |
break; |
case AAPLTicTacToeGameStateXWin: |
self.statusText.stringValue = NSLocalizedString(@"X wins!", nil); |
break; |
case AAPLTicTacToeGameStateOWin: |
self.statusText.stringValue = NSLocalizedString(@"O Wins!", nil); |
break; |
case AAPLTicTacToeGameStateTie: |
self.statusText.stringValue = NSLocalizedString(@"It's a tie", nil); |
break; |
default: |
break; |
} |
self.difficultyText.integerValue = self.ai.difficulty; |
self.increaseDifficultyButton.enabled = (self.ai.difficulty != AAPLMaxDifficulty); |
self.decreaseDifficultyButton.enabled = (self.ai.difficulty != AAPLMinDifficulty); |
} |
- (BOOL)takeAITurn |
{ |
return self.game.state == AAPLTicTacToeGameStateOTurn && self.playAICheckbox.checked; |
} |
#pragma mark - Board View Delegate Methods |
- (void)playSquareAtRow:(NSUInteger)row column:(NSUInteger)column |
{ |
[self.game playSquareAtRow:row column:column]; |
AAPLTicTacToeSquare *aiSquare = nil; |
NSUInteger aiRow = 0; |
NSUInteger aiColumn = 0; |
if ( [self takeAITurn] ) |
{ |
NSPoint move = [self.ai moveForBoard:self.game.board]; |
aiRow = move.x; |
aiColumn = move.y; |
aiSquare = [self.game playSquareAtRow:aiRow column:aiColumn]; |
} |
[self refresh]; |
[self announceTurnWithAISquare:aiSquare row:aiRow column:aiColumn]; |
} |
- (AAPLTicTacToeSquare *)squareAtRow:(NSUInteger)row column:(NSUInteger)column |
{ |
return [self.game.board squareAtRow:row column:column]; |
} |
- (BOOL)isGameOver |
{ |
return self.game.state != AAPLTicTacToeGameStateOTurn && |
self.game.state != AAPLTicTacToeGameStateXTurn; |
} |
#pragma mark - Checkbox Delegate Methods |
- (void)checkboxCheckedStateChanged:(id)sender |
{ |
if ( sender == self.playAICheckbox && [self takeAITurn] ) |
{ |
NSPoint move = [self.ai moveForBoard:self.game.board]; |
NSUInteger row = move.x; |
NSUInteger column = move.y; |
AAPLTicTacToeSquare *square = [self.game playSquareAtRow:row column:column]; |
[self announceTurnWithAISquare:square row:row column:column]; |
} |
} |
#pragma mark - Reset Button Delegate Methods |
- (void)buttonPressed:(id)sender |
{ |
if ( sender == self.resetGameButton ) |
{ |
[self.game reset]; |
[self refresh]; |
} |
} |
#pragma mark - Increase/Decrease Difficulty Actions |
- (IBAction)decreaseDifficulty:(id)sender |
{ |
NSInteger difficulty = self.difficultyText.integerValue; |
self.ai.difficulty = MAX(difficulty - 1, AAPLMinDifficulty); |
[self refresh]; |
} |
- (IBAction)increaseDifficulty:(id)sender |
{ |
NSInteger difficulty = self.difficultyText.integerValue; |
self.ai.difficulty = MIN(difficulty + 1, AAPLMaxDifficulty); |
[self refresh]; |
} |
#pragma mark - Menu Actions |
- (IBAction)playTopLeft:(id)sender |
{ |
[self playSquareAtRow:0 column:0]; |
} |
- (IBAction)playTop:(id)sender |
{ |
[self playSquareAtRow:0 column:1]; |
} |
- (IBAction)playTopRight:(id)sender |
{ |
[self playSquareAtRow:0 column:2]; |
} |
- (IBAction)playLeft:(id)sender |
{ |
[self playSquareAtRow:1 column:0]; |
} |
- (IBAction)playCenter:(id)sender |
{ |
[self playSquareAtRow:1 column:1]; |
} |
- (IBAction)playRight:(id)sender |
{ |
[self playSquareAtRow:1 column:2]; |
} |
- (IBAction)playBottomLeft:(id)sender |
{ |
[self playSquareAtRow:2 column:0]; |
} |
- (IBAction)playBottom:(id)sender |
{ |
[self playSquareAtRow:2 column:1]; |
} |
- (IBAction)playBottomRight:(id)sender |
{ |
[self playSquareAtRow:2 column:2]; |
} |
#pragma mark - Accessibility Announcements |
// When a square is played, announce the AI player's move (if enabled) and the next player's turn or game outcome. |
- (void)announceTurnWithAISquare:(AAPLTicTacToeSquare *)aiSquare row:(NSUInteger)row column:(NSUInteger)column |
{ |
NSString *announcement; |
NSString *statusText = self.statusText.stringValue; |
if ( aiSquare ) |
{ |
NSString *computerPlayedFormatter = NSLocalizedString(@"ComputerPlayedFormatter", nil); |
NSString *computerPlayedAndStatusFormatter = NSLocalizedString(@"ComputerPlayerAndStatusFormatter", nil); |
NSString *aiMove = [NSString stringWithFormat:computerPlayedFormatter, [AAPLTicTacToeBoard descriptionForSquare:aiSquare row:row column:column]]; |
announcement = [NSString stringWithFormat:computerPlayedAndStatusFormatter, aiMove, statusText]; |
} |
else |
{ |
announcement = statusText; |
} |
NSDictionary *userInfo = @{NSAccessibilityAnnouncementKey : announcement, |
NSAccessibilityPriorityKey : @(NSAccessibilityPriorityMedium)}; |
NSAccessibilityPostNotificationWithUserInfo(self.boardView, NSAccessibilityAnnouncementRequestedNotification, userInfo); |
} |
@end |
Copyright © 2016 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2016-02-18