ios/tutorials/tutorial3/TicTacToe/TicTacToe/TicTacToeViewController.swift (90 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 SnapKit import UIKit protocol TicTacToePresentableListener: AnyObject { func placeCurrentPlayerMark(atRow row: Int, col: Int) func closeGame() } final class TicTacToeViewController: UIViewController, TicTacToePresentable, TicTacToeViewControllable { weak var listener: TicTacToePresentableListener? init() { super.init(nibName: nil, bundle: nil) } required init?(coder aDecoder: NSCoder) { fatalError("Method is not supported") } override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = UIColor.yellow buildCollectionView() } // MARK: - TicTacToePresentable func setCell(atRow row: Int, col: Int, withPlayerType playerType: PlayerType) { let indexPathRow = row * GameConstants.colCount + col let cell = collectionView.cellForItem(at: IndexPath(row: indexPathRow, section: Constants.sectionCount - 1)) cell?.backgroundColor = playerType.color } func announce(winner: PlayerType) { let winnerString: String = { switch winner { case .player1: return "Red" case .player2: return "Blue" } }() let alert = UIAlertController(title: "\(winnerString) Won!", message: nil, preferredStyle: .alert) let closeAction = UIAlertAction(title: "Close Game", style: UIAlertActionStyle.default) { [weak self] _ in self?.listener?.closeGame() } alert.addAction(closeAction) present(alert, animated: true, completion: nil) } // MARK: - Private private lazy var collectionView: UICollectionView = { let layout = UICollectionViewFlowLayout() layout.minimumLineSpacing = 0 layout.minimumInteritemSpacing = 0 layout.itemSize = CGSize(width: Constants.cellSize, height: Constants.cellSize) return UICollectionView(frame: CGRect.zero, collectionViewLayout: layout) }() private func buildCollectionView() { collectionView.dataSource = self collectionView.delegate = self collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: Constants.cellIdentifier) view.addSubview(collectionView) collectionView.snp.makeConstraints { (maker: ConstraintMaker) in maker.center.equalTo(self.view.snp.center) maker.size.equalTo(CGSize(width: CGFloat(GameConstants.colCount) * Constants.cellSize, height: CGFloat(GameConstants.rowCount) * Constants.cellSize)) } } } fileprivate struct Constants { static let sectionCount = 1 static let cellSize: CGFloat = UIScreen.main.bounds.width / CGFloat(GameConstants.colCount) static let cellIdentifier = "TicTacToeCell" static let defaultColor = UIColor.white } extension TicTacToeViewController: UICollectionViewDataSource { func numberOfSections(in collectionView: UICollectionView) -> Int { return Constants.sectionCount } func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return GameConstants.rowCount * GameConstants.colCount } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let reusedCell = collectionView.dequeueReusableCell(withReuseIdentifier: Constants.cellIdentifier, for: indexPath) reset(cell: reusedCell) return reusedCell } private func reset(cell: UICollectionViewCell) { cell.backgroundColor = Constants.defaultColor cell.contentView.layer.borderWidth = 2 cell.contentView.layer.borderColor = UIColor.lightGray.cgColor } } // MARK: - UICollectionViewDelegate extension TicTacToeViewController: UICollectionViewDelegate { func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { let row = indexPath.row / GameConstants.colCount let col = indexPath.row - row * GameConstants.rowCount listener?.placeCurrentPlayerMark(atRow: row, col: col) } }