// // 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) } }