昨日までで、モデルの大部分は実装できた。
今日は、これらを繋ぎ合わせて動作させるコントローラを実装していく。
GameControllerクラス
コントローラはビューとモデルを結びつける「糊」の役割を果たすので、UIごとに作っていくことになる。
ここで作るのは、CUI用のコントローラ。
//============================== // BirdHead //------------------------------ // GameController.swift //============================== import Foundation class GameController: GameInfoObserver { // 続く
GameInfoObserverプロトコルに準拠して、オブザーバになるようにしている。
プロパティとイニシャライザ
まずはプロパティとイニシャライザ。
// 続き private var gameInfo: GameInfo private var players: [Player] var output: Bool var learn: Bool init(gameInfo: GameInfo, players: [Player]) { self.gameInfo = gameInfo self.players = players self.output = false self.learn = false self.gameInfo.addObserver(self) } // 続く
プロパティとして、出力を行うのかと、プレイヤーに学習を行わせるのかのフラグを持たせている。
あと、初期化のときに自身をオブザーバとして登録するようにしている。
ゲームの進行
次に、ゲームの進行
// 続き func start() throws { while !self.gameInfo.isEnd { if !self.gameInfo.inDeal { if self.output { print("--------------------") print("deal...") print("----------") } try! self.gameInfo.deal() } let playerIndex = self.gameInfo.turnPlayerIndex let player = self.players[playerIndex] if self.output { print("[\(player.name)]") } let view = try! self.gameInfo.playerViewFor(playerIndex) let action = try player.select(view) if self.output { print("selected action: \(action)") } try! self.gameInfo.doAction(action) } } // 続く
やっていることはシンプルで、ディールの最初ならカードの分配を行って、あとは、手番プレイヤーを知り、そのプレイヤーにアクションの選択をさせ、選択されたアクションをゲーム情報に対して実行する、というのを繰り返しているだけ。
ここで、プレイヤーがアクションの選択をキャンセルする可能性があるので、その場合は例外をただ呼び出し元に投げるようにしている。
(例外が使えるって素晴らしいね!)
オブザーバとしての各メソッドの実装
最後に、オブザーバとしての各メソッドの実装。
// 続き func gameInfoResolvedTrick(trickCount: Int, winner playerIndex: Int) { if self.output { print("----------") print("trick \(trickCount) is done.") print("\(self.players[playerIndex].name) takes trick.") print("----------") } if self.learn { for player in self.players { player.learn(0) } } } func gameInfoResolvedDeal(loserIndices: [Int], lastCards: [Int]) { if self.output { print("deal is done.") print("last cards:") for i in 0..<self.players.count { print("\(self.players[i].name): \(lastCards[i])") } print(loserIndices.map {(i: Int) -> String in self.players[i].name}, terminator: "") print(" lose in deal.") print("minus points:") for i in 0..<players.count { print("\(players[i].name): \(self.gameInfo.minusPointCards[i])") } } if self.learn { for i in 0..<self.players.count { if loserIndices.indexOf(i) != nil { self.players[i].learn(lastCards[i]) } else { self.players[i].learn(0) } } } } func gameInfoEnded() { if self.output { print("--------------------") print("game ended.") var losePlayerIndices: [Int] = [Int]() print("total minus points:") for i in 0..<self.players.count { var minusSum: Int = 0 for minusPoint in self.gameInfo.minusPointCards[i] { minusSum += minusPoint } print("\(self.players[i].name): \(minusSum)") if minusSum >= GameInfo.LosePoint { losePlayerIndices.append(i) } } print(losePlayerIndices.map {(i: Int) -> String in self.players[i].name}, terminator: "") print(" lose.") } } }
通知がきたタイミングで、必要なら情報の出力、それとプレイヤーへ学習を行わせるということを行っている。
これでコントローラの実装も完了。
残すは実際のプレイヤーの実装のみ。
今日はここまで!