Last active
          March 23, 2018 16:37 
        
      - 
      
 - 
        
Save nerdo/24d24a432bcde285f42e69328bbcbca4 to your computer and use it in GitHub Desktop.  
Revisions
- 
        
nerdo revised this gist
Mar 23, 2018 . 1 changed file with 12 additions and 7 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -11,7 +11,7 @@ import ReSwift open class TicTacToe { public typealias Winner = (player: Player, path: [Int]) public static var store = Store<State>(reducer: Reducer.ticTacToe, state: nil) public enum Player: String { case x = "X" @@ -34,17 +34,16 @@ open class TicTacToe { } open class Reducer { static func ticTacToe(action: ReSwift.Action, state: State?) -> State { var state = state ?? State() state = self.reset(action: action, state: state) state = self.move(action: action, state: state) return state } private static func reset(action: ReSwift.Action, state: State?) -> State { var state = state ?? State() guard let action = action as? Action else { @@ -58,7 +57,13 @@ open class TicTacToe { return state } private static func move(action: ReSwift.Action, state: State?) -> State { var state = self.handlePlayerMove(action: action, state: state) state = self.checkForWinner(action: action, state: state) return state } private static func handlePlayerMove(action: ReSwift.Action, state: State?) -> State { var state = state ?? State() guard let action = action as? Action else {  - 
        
nerdo created this gist
Mar 22, 2018 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,214 @@ <?xml version="1.0" encoding="UTF-8"?> <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r"> <device id="retina4_7" orientation="portrait"> <adaptation id="fullscreen"/> </device> <dependencies> <deployment identifier="iOS"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/> <capability name="Aspect ratio constraints" minToolsVersion="5.1"/> <capability name="Safe area layout guides" minToolsVersion="9.0"/> <capability name="Stack View standard spacing" minToolsVersion="9.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <scenes> <!--View Controller--> <scene sceneID="tne-QT-ifu"> <objects> <viewController id="BYZ-38-t0r" customClass="ViewController" customModule="TicTacToe" customModuleProvider="target" sceneMemberID="viewController"> <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC"> <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillEqually" spacingType="standard" translatesAutoresizingMaskIntoConstraints="NO" id="GYC-JQ-41v"> <rect key="frame" x="15" y="161" width="345" height="345"/> <subviews> <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacingType="standard" translatesAutoresizingMaskIntoConstraints="NO" id="v7b-c4-5Ke"> <rect key="frame" x="0.0" y="0.0" width="345" height="109.5"/> <subviews> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="2cU-au-Mow"> <rect key="frame" x="0.0" y="0.0" width="109.5" height="109.5"/> <color key="backgroundColor" red="0.92143100499999997" green="0.92145264149999995" blue="0.92144101860000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <fontDescription key="fontDescription" type="system" weight="heavy" pointSize="32"/> <state key="normal"> <color key="titleColor" red="0.12984204290000001" green="0.12984612579999999" blue="0.12984395030000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> </state> <connections> <action selector="button0Pressed:" destination="BYZ-38-t0r" eventType="touchUpInside" id="82X-ZM-363"/> </connections> </button> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="drs-Bo-49n"> <rect key="frame" x="117.5" y="0.0" width="110" height="109.5"/> <color key="backgroundColor" red="0.92143100499999997" green="0.92145264149999995" blue="0.92144101860000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <fontDescription key="fontDescription" type="system" weight="heavy" pointSize="32"/> <state key="normal"> <color key="titleColor" red="0.12984204290000001" green="0.12984612579999999" blue="0.12984395030000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> </state> <connections> <action selector="button1Pressed:" destination="BYZ-38-t0r" eventType="touchUpInside" id="y6O-wU-B7p"/> </connections> </button> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="C4m-5v-2rO"> <rect key="frame" x="235.5" y="0.0" width="109.5" height="109.5"/> <color key="backgroundColor" red="0.92143100499999997" green="0.92145264149999995" blue="0.92144101860000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <fontDescription key="fontDescription" type="system" weight="heavy" pointSize="32"/> <state key="normal"> <color key="titleColor" red="0.12984204290000001" green="0.12984612579999999" blue="0.12984395030000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> </state> <connections> <action selector="button2Pressed:" destination="BYZ-38-t0r" eventType="touchUpInside" id="KVg-VM-FO8"/> </connections> </button> </subviews> </stackView> <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacingType="standard" translatesAutoresizingMaskIntoConstraints="NO" id="IDm-oR-oQE"> <rect key="frame" x="0.0" y="117.5" width="345" height="110"/> <subviews> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="YtA-u5-gCw"> <rect key="frame" x="0.0" y="0.0" width="109.5" height="110"/> <color key="backgroundColor" red="0.92143100499999997" green="0.92145264149999995" blue="0.92144101860000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <fontDescription key="fontDescription" type="system" weight="heavy" pointSize="32"/> <state key="normal"> <color key="titleColor" red="0.12984204290000001" green="0.12984612579999999" blue="0.12984395030000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> </state> <connections> <action selector="button3Pressed:" destination="BYZ-38-t0r" eventType="touchUpInside" id="M7o-Ua-KhF"/> </connections> </button> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="lnr-Ld-pnz"> <rect key="frame" x="117.5" y="0.0" width="110" height="110"/> <color key="backgroundColor" red="0.92143100499999997" green="0.92145264149999995" blue="0.92144101860000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <fontDescription key="fontDescription" type="system" weight="heavy" pointSize="32"/> <state key="normal"> <color key="titleColor" red="0.12984204290000001" green="0.12984612579999999" blue="0.12984395030000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> </state> <connections> <action selector="button4Pressed:" destination="BYZ-38-t0r" eventType="touchUpInside" id="wNY-9B-ocj"/> </connections> </button> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="tTU-Xd-RTN"> <rect key="frame" x="235.5" y="0.0" width="109.5" height="110"/> <color key="backgroundColor" red="0.92143100499999997" green="0.92145264149999995" blue="0.92144101860000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <fontDescription key="fontDescription" type="system" weight="heavy" pointSize="32"/> <state key="normal"> <color key="titleColor" red="0.12984204290000001" green="0.12984612579999999" blue="0.12984395030000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> </state> <connections> <action selector="button5Pressed:" destination="BYZ-38-t0r" eventType="touchUpInside" id="yNV-Mf-v4H"/> </connections> </button> </subviews> </stackView> <stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacingType="standard" translatesAutoresizingMaskIntoConstraints="NO" id="wO4-X9-a35"> <rect key="frame" x="0.0" y="235.5" width="345" height="109.5"/> <subviews> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="S5y-Gp-PXp"> <rect key="frame" x="0.0" y="0.0" width="109.5" height="109.5"/> <color key="backgroundColor" red="0.92143100499999997" green="0.92145264149999995" blue="0.92144101860000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <fontDescription key="fontDescription" type="system" weight="heavy" pointSize="32"/> <state key="normal"> <color key="titleColor" red="0.12984204290000001" green="0.12984612579999999" blue="0.12984395030000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> </state> <connections> <action selector="button6Pressed:" destination="BYZ-38-t0r" eventType="touchUpInside" id="fwN-Ea-0nP"/> </connections> </button> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="DZE-sb-KSR"> <rect key="frame" x="117.5" y="0.0" width="110" height="109.5"/> <color key="backgroundColor" red="0.92143100499999997" green="0.92145264149999995" blue="0.92144101860000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <fontDescription key="fontDescription" type="system" weight="heavy" pointSize="32"/> <state key="normal"> <color key="titleColor" red="0.12984204290000001" green="0.12984612579999999" blue="0.12984395030000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> </state> <connections> <action selector="button7Pressed:" destination="BYZ-38-t0r" eventType="touchUpInside" id="qKa-ck-me6"/> </connections> </button> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="HN8-ZY-CpP"> <rect key="frame" x="235.5" y="0.0" width="109.5" height="109.5"/> <color key="backgroundColor" red="0.92143100499999997" green="0.92145264149999995" blue="0.92144101860000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <fontDescription key="fontDescription" type="system" weight="heavy" pointSize="32"/> <state key="normal"> <color key="titleColor" red="0.12984204290000001" green="0.12984612579999999" blue="0.12984395030000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> </state> <connections> <action selector="button8Pressed:" destination="BYZ-38-t0r" eventType="touchUpInside" id="Ule-JU-klE"/> </connections> </button> </subviews> </stackView> </subviews> <constraints> <constraint firstAttribute="width" secondItem="GYC-JQ-41v" secondAttribute="height" multiplier="1:1" id="1Ir-Zn-ZiX"/> </constraints> </stackView> <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="YVy-GY-iZt"> <rect key="frame" x="111.5" y="104" width="152" height="49"/> <color key="backgroundColor" red="0.016804177310000001" green="0.19835099580000001" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <fontDescription key="fontDescription" type="system" pointSize="24"/> <inset key="contentEdgeInsets" minX="10" minY="10" maxX="10" maxY="10"/> <state key="normal" title="PLAY AGAIN"> <color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> </state> <connections> <action selector="playAgain:" destination="BYZ-38-t0r" eventType="touchUpInside" id="y0M-27-msF"/> </connections> </button> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Z Won!" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="XL9-cY-Sce"> <rect key="frame" x="138" y="514" width="99" height="38.5"/> <fontDescription key="fontDescription" type="system" pointSize="32"/> <nil key="textColor"/> <nil key="highlightedColor"/> </label> </subviews> <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <constraints> <constraint firstItem="XL9-cY-Sce" firstAttribute="centerX" secondItem="GYC-JQ-41v" secondAttribute="centerX" id="0S8-2B-MAc"/> <constraint firstItem="GYC-JQ-41v" firstAttribute="centerY" secondItem="8bC-Xf-vdC" secondAttribute="centerY" id="5my-Tr-Ff6"/> <constraint firstItem="GYC-JQ-41v" firstAttribute="top" relation="greaterThanOrEqual" secondItem="6Tk-OE-BBY" secondAttribute="top" constant="65" id="D0B-8f-seN"/> <constraint firstItem="XL9-cY-Sce" firstAttribute="top" secondItem="GYC-JQ-41v" secondAttribute="bottom" constant="8" symbolic="YES" id="Ecy-HS-Eaw"/> <constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="GYC-JQ-41v" secondAttribute="trailing" constant="15" id="SAa-sC-3vU"/> <constraint firstItem="GYC-JQ-41v" firstAttribute="height" secondItem="6Tk-OE-BBY" secondAttribute="height" priority="750" id="SGK-vz-AuA"/> <constraint firstItem="YVy-GY-iZt" firstAttribute="centerX" secondItem="GYC-JQ-41v" secondAttribute="centerX" id="XeQ-MS-qYm"/> <constraint firstItem="GYC-JQ-41v" firstAttribute="top" secondItem="YVy-GY-iZt" secondAttribute="bottom" constant="8" symbolic="YES" id="cua-PS-2Ah"/> <constraint firstItem="6Tk-OE-BBY" firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="GYC-JQ-41v" secondAttribute="bottom" constant="50" id="pDf-n6-QyB"/> <constraint firstItem="GYC-JQ-41v" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="15" id="rP6-im-sYS"/> <constraint firstItem="GYC-JQ-41v" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="y7y-qw-7Jy"/> </constraints> <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/> <variation key="default"> <mask key="constraints"> <exclude reference="pDf-n6-QyB"/> <exclude reference="D0B-8f-seN"/> <exclude reference="SGK-vz-AuA"/> </mask> </variation> <variation key="heightClass=compact"> <mask key="constraints"> <exclude reference="SAa-sC-3vU"/> <include reference="pDf-n6-QyB"/> <include reference="D0B-8f-seN"/> <include reference="SGK-vz-AuA"/> <exclude reference="rP6-im-sYS"/> </mask> </variation> </view> <connections> <outlet property="button0" destination="2cU-au-Mow" id="udq-uF-Eak"/> <outlet property="button1" destination="drs-Bo-49n" id="PrU-gF-4oa"/> <outlet property="button2" destination="C4m-5v-2rO" id="fdE-sp-oC5"/> <outlet property="button3" destination="YtA-u5-gCw" id="3Vz-n5-w01"/> <outlet property="button4" destination="lnr-Ld-pnz" id="rZc-UI-8Sc"/> <outlet property="button5" destination="tTU-Xd-RTN" id="cIr-hZ-04Q"/> <outlet property="button6" destination="S5y-Gp-PXp" id="yMU-9m-uCS"/> <outlet property="button7" destination="DZE-sb-KSR" id="HcP-JR-cxR"/> <outlet property="button8" destination="HN8-ZY-CpP" id="410-BS-gY0"/> <outlet property="playAgainButton" destination="YVy-GY-iZt" id="czv-PK-bW4"/> <outlet property="winnerLabel" destination="XL9-cY-Sce" id="dG6-ga-Uyr"/> </connections> </viewController> <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/> </objects> </scene> </scenes> </document> This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,112 @@ // // TicTacToe.swift // TicTacToe // // Created by Dannel Albert on 3/22/18. // Copyright © 2018 Dannel Albert. All rights reserved. // import ReSwift open class TicTacToe { public typealias Winner = (player: Player, path: [Int]) public static var store = Store<State>(reducer: Reducer.game, state: nil) public enum Player: String { case x = "X" case o = "O" } public struct State: ReSwift.StateType { var board: [Player?] = [ nil, nil, nil, nil, nil, nil, nil, nil, nil ] var currentPlayer: Player = .x var winner: Winner? } public enum Action: ReSwift.Action { case move(location: Int) case reset } open class Reducer { static func game(action: ReSwift.Action, state: State?) -> State { var state = state ?? State() state = self.checkForReset(action: action, state: state) state = self.updateBoard(action: action, state: state) state = self.checkForWinner(action: action, state: state) return state } private static func checkForReset(action: ReSwift.Action, state: State?) -> State { var state = state ?? State() guard let action = action as? Action else { return state } if case .reset = action { state = State() } return state } private static func updateBoard(action: ReSwift.Action, state: State?) -> State { var state = state ?? State() guard let action = action as? Action else { return state } if case let .move(location) = action { if location >= 0 && location < 9 && state.board[location] == nil { state.board[location] = state.currentPlayer switch state.currentPlayer { case .x: state.currentPlayer = .o case .o: state.currentPlayer = .x } } } return state } private static func checkForWinner(action: ReSwift.Action, state: State?) -> State { var state = state ?? State() var winner: Winner? winner = winner ?? self.getWinner(state.board, 0, 1, 2) winner = winner ?? self.getWinner(state.board, 3, 4, 5) winner = winner ?? self.getWinner(state.board, 6, 7, 8) winner = winner ?? self.getWinner(state.board, 0, 3, 6) winner = winner ?? self.getWinner(state.board, 1, 4, 7) winner = winner ?? self.getWinner(state.board, 2, 5, 8) winner = winner ?? self.getWinner(state.board, 0, 4, 8) winner = winner ?? self.getWinner(state.board, 2, 4, 6) state.winner = winner return state } private static func getWinner(_ board: [Player?], _ a: Int, _ b: Int, _ c: Int) -> Winner? { if board[a] == nil || board[b] == nil || board[c] == nil { return nil } if board[a] == board[b] && board[b] == board[c] { return (player: board[a]!, path: [a, b, c]) } return nil } } } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,168 @@ // // ViewController.swift // TicTacToe // // Created by Dannel Albert on 3/22/18. // Copyright © 2018 Dannel Albert. All rights reserved. // import UIKit import ReSwift class ViewController: UIViewController, StoreSubscriber { @IBOutlet weak var button0: UIButton! @IBOutlet weak var button1: UIButton! @IBOutlet weak var button2: UIButton! @IBOutlet weak var button3: UIButton! @IBOutlet weak var button4: UIButton! @IBOutlet weak var button5: UIButton! @IBOutlet weak var button6: UIButton! @IBOutlet weak var button7: UIButton! @IBOutlet weak var button8: UIButton! @IBOutlet weak var playAgainButton: UIButton! @IBOutlet weak var winnerLabel: UILabel! var buttons: [UIButton]! override func viewDidLoad() { super.viewDidLoad() setupButtons() TicTacToe.store.subscribe(self) } func newState(state: TicTacToe.State) { DispatchQueue.main.async { self.render(state: state) } if state.currentPlayer == .o { DispatchQueue.global(qos: .background).async { self.computerMove(state: state) } } } func render(state: TicTacToe.State) { let thereIsAWinner = state.winner != nil let hasMovesLeft = state.board.filter { $0 == nil }.count > 0 playAgainButton.isHidden = !thereIsAWinner && hasMovesLeft winnerLabel.isHidden = !thereIsAWinner && hasMovesLeft for (i, player) in state.board.enumerated() { if let player = player { buttons[i].setTitle(player.rawValue, for: .normal) } else { buttons[i].setTitle(nil, for: .normal) } if state.winner?.path.contains(i) == true { buttons[i].backgroundColor = .green } else { buttons[i].backgroundColor = .lightGray } } if let winner = state.winner { winnerLabel.text = "\(winner.player.rawValue) Won!" } else if !hasMovesLeft { winnerLabel.text = "It's a draw!" } for button in buttons { button.isEnabled = state.currentPlayer == .x && !thereIsAWinner && hasMovesLeft } #if DEBUG renderTextBoard(state: state) #endif } func renderTextBoard(state: TicTacToe.State) { let board = state.board.map { $0?.rawValue ?? " " } print() print(" \(board[0]) | \(board[1]) | \(board[2])") print("-----------") print(" \(board[3]) | \(board[4]) | \(board[5])") print("-----------") print(" \(board[6]) | \(board[7]) | \(board[8])") if let winner = state.winner { print("\(winner.player.rawValue) Won!") } print() } private func setupButtons() { buttons = [ button0, button1, button2, button3, button4, button5, button6, button7, button8 ] } func computerMove(state: TicTacToe.State) { if state.winner != nil { return } let emptyLocations = state.board .enumerated() .map { (player: $1, location: $0) } .filter { $0.player == nil } .map { $0.location } if emptyLocations.count == 0 { return } let location = emptyLocations[Int(arc4random_uniform(UInt32(emptyLocations.count)))] TicTacToe.store.dispatch( TicTacToe.Action.move(location: location) ) } @IBAction func button0Pressed(_ sender: Any) { TicTacToe.store.dispatch(TicTacToe.Action.move(location: 0)) } @IBAction func button1Pressed(_ sender: Any) { TicTacToe.store.dispatch(TicTacToe.Action.move(location: 1)) } @IBAction func button2Pressed(_ sender: Any) { TicTacToe.store.dispatch(TicTacToe.Action.move(location: 2)) } @IBAction func button3Pressed(_ sender: Any) { TicTacToe.store.dispatch(TicTacToe.Action.move(location: 3)) } @IBAction func button4Pressed(_ sender: Any) { TicTacToe.store.dispatch(TicTacToe.Action.move(location: 4)) } @IBAction func button5Pressed(_ sender: Any) { TicTacToe.store.dispatch(TicTacToe.Action.move(location: 5)) } @IBAction func button6Pressed(_ sender: Any) { TicTacToe.store.dispatch(TicTacToe.Action.move(location: 6)) } @IBAction func button7Pressed(_ sender: Any) { TicTacToe.store.dispatch(TicTacToe.Action.move(location: 7)) } @IBAction func button8Pressed(_ sender: Any) { TicTacToe.store.dispatch(TicTacToe.Action.move(location: 8)) } @IBAction func playAgain(_ sender: Any) { TicTacToe.store.dispatch(TicTacToe.Action.reset) } deinit { TicTacToe.store.unsubscribe(self) } }