parent
e286e7e78a
commit
7206c0fa14
@ -0,0 +1,82 @@
|
||||
public struct TicTacToeRules: Rules {
|
||||
public var state: GameState = .Playing(turn: .A)
|
||||
|
||||
public var history: [Move] = []
|
||||
|
||||
private let columns: Int, rows: Int, minAligned: Int
|
||||
|
||||
public init(columns: Int, rows: Int, minAligned: Int = 3) {
|
||||
self.columns = columns
|
||||
self.rows = rows
|
||||
self.minAligned = minAligned
|
||||
}
|
||||
|
||||
public func createBoard() -> Board {
|
||||
Board(columns: self.columns, rows: self.rows)!
|
||||
}
|
||||
|
||||
public func isValid(board: Board) -> Bool {
|
||||
abs(board.countPieces(filter: { p in p.owner == .A }) -
|
||||
board.countPieces(filter: { p in p.owner == .B })) <= 1
|
||||
}
|
||||
|
||||
public func isValid(board: Board, move: Move) -> Bool {
|
||||
guard self.isValid(board: board) else { return false }
|
||||
|
||||
guard case .Playing(let turn) = state, turn == move.player else { return false }
|
||||
|
||||
if case .InsertAt(let coord) = move.action, board.isInBounds(coord) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
public func validMoves(board: Board) -> [Move] {
|
||||
let player = Self.nextPlayer(board: board)
|
||||
|
||||
return self.validMoves(board: board, for_player: player).map { Move(player: player, action: $0) }
|
||||
}
|
||||
|
||||
private static func nextPlayer(board: Board) -> Player {
|
||||
if board.countPieces(filter: { p in p.owner == .A }) > board.countPieces(filter: { p in p.owner == .B }) {
|
||||
.B
|
||||
} else {
|
||||
.A
|
||||
}
|
||||
}
|
||||
|
||||
public func validMoves(board: Board, for_player player: Player) -> [Move.Action] {
|
||||
var moves: [Move.Action] = []
|
||||
|
||||
for col in 0..<board.columns {
|
||||
for row in 0..<board.rows {
|
||||
if board[col, row] == nil {
|
||||
moves.append(.InsertAt(where: Coords(col, row)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return moves
|
||||
}
|
||||
|
||||
public mutating func onMoveDone(move: Move, board: Board) {
|
||||
self.history.append(move)
|
||||
|
||||
guard case .InsertAt(let coords) = move.action else {
|
||||
fatalError("Illegal move \(move.action)")
|
||||
}
|
||||
|
||||
if FourInARowRules.countMaxRow(center: coords, board: board) >= self.minAligned {
|
||||
self.state = .Finished(winner: move.player)
|
||||
} else if board.countPieces() == board.columns * board.rows {
|
||||
self.state = .Finished(winner: nil)
|
||||
} else {
|
||||
let next: Player = switch move.player {
|
||||
case .A: .B
|
||||
case .B: .A
|
||||
}
|
||||
self.state = .Playing(turn: next)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in new issue