tutorials/tutorial3/TicTacToe/TicTacToe/TicTacToeInteractor.swift (103 lines of code) (raw):
//
// Copyright (c) 2017. Uber Technologies
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import RIBs
import RxSwift
protocol TicTacToeRouting: ViewableRouting {
// TODO: Declare methods the interactor can invoke to manage sub-tree via the router.
}
protocol TicTacToePresentable: Presentable {
var listener: TicTacToePresentableListener? { get set }
func setCell(atRow row: Int, col: Int, withPlayerType playerType: PlayerType)
func announce(winner: PlayerType)
}
protocol TicTacToeListener: AnyObject {
func gameDidEnd()
}
final class TicTacToeInteractor: PresentableInteractor<TicTacToePresentable>, TicTacToeInteractable, TicTacToePresentableListener {
weak var router: TicTacToeRouting?
weak var listener: TicTacToeListener?
// TODO: Add additional dependencies to constructor. Do not perform any logic
// in constructor.
override init(presenter: TicTacToePresentable) {
super.init(presenter: presenter)
presenter.listener = self
}
override func didBecomeActive() {
super.didBecomeActive()
initBoard()
}
override func willResignActive() {
super.willResignActive()
// TODO: Pause any business logic.
}
// MARK: - TicTacToePresentableListener
func placeCurrentPlayerMark(atRow row: Int, col: Int) {
guard board[row][col] == nil else {
return
}
let currentPlayer = getAndFlipCurrentPlayer()
board[row][col] = currentPlayer
presenter.setCell(atRow: row, col: col, withPlayerType: currentPlayer)
if let winner = checkWinner() {
presenter.announce(winner: winner)
}
}
func closeGame() {
listener?.gameDidEnd()
}
// MARK: - Private
private var currentPlayer = PlayerType.player1
private var board = [[PlayerType?]]()
private func initBoard() {
for _ in 0..<GameConstants.rowCount {
board.append([nil, nil, nil])
}
}
private func getAndFlipCurrentPlayer() -> PlayerType {
let currentPlayer = self.currentPlayer
self.currentPlayer = currentPlayer == .player1 ? .player2 : .player1
return currentPlayer
}
private func checkWinner() -> PlayerType? {
// Rows.
for row in 0..<GameConstants.rowCount {
guard let assumedWinner = board[row][0] else {
continue
}
var winner: PlayerType? = assumedWinner
for col in 1..<GameConstants.colCount {
if assumedWinner.rawValue != board[row][col]?.rawValue {
winner = nil
break
}
}
if let winner = winner {
return winner
}
}
// Cols.
for col in 0..<GameConstants.colCount {
guard let assumedWinner = board[0][col] else {
continue
}
var winner: PlayerType? = assumedWinner
for row in 1..<GameConstants.rowCount {
if assumedWinner.rawValue != board[row][col]?.rawValue {
winner = nil
break
}
}
if let winner = winner {
return winner
}
}
// Diagonal.
guard let p11 = board[1][1] else {
return nil
}
if let p00 = board[0][0], let p22 = board[2][2] {
if p00.rawValue == p11.rawValue && p11.rawValue == p22.rawValue {
return p11
}
}
if let p02 = board[0][2], let p20 = board[2][0] {
if p02.rawValue == p11.rawValue && p11.rawValue == p20.rawValue {
return p11
}
}
return nil
}
}
struct GameConstants {
static let rowCount = 3
static let colCount = 3
}