You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
Connect4/Model/Sources/Model/Board.swift

144 lines
3.9 KiB

public struct Board {
private var grid: [[Piece?]]
public var columns: Int { return grid.count }
public var rows: Int { return grid.first!.count }
public init?(columns: Int, rows: Int) {
self.init(grid: Array(repeating: Array(repeating: nil, count: rows), count: columns))
}
public init?(grid: [[Piece?]]) {
guard !grid.isEmpty, !grid.first!.isEmpty else {
return nil
}
self.grid = grid
}
private func checkBounds(_ column: Int, _ row: Int) {
precondition(column >= 0 && column < self.columns && row >= 0 && row < self.rows, "Coordinates out of bounds")
}
public subscript(column: Int, row: Int) -> Piece? {
get {
checkBounds(column, row)
return grid[column][row]
}
set {
checkBounds(column, row)
grid[column][row] = newValue
}
}
public func countPieces() -> (a: Int, b: Int) {
var a = 0
var b = 0
for column in grid {
for piece in column {
switch piece {
case .PlayerA:
a += 1
case .PlayerB:
b += 1
case nil:
break
}
}
}
return (a, b)
}
@discardableResult
public mutating func insert(piece: Piece, side: Side = .Top, offset: Int, pushing push: Bool = false) -> Bool {
precondition(offset >= 0, "Offset out of bounds")
switch side {
case .Top:
precondition(offset < self.columns, "Offset (column) out of bounds")
if self.grid[offset].first! != nil {
if (!push) {
return false
}
Board.shiftDown(column: &self.grid[offset])
}
self.grid[offset][0] = piece
return true
case .Left:
precondition(offset < self.rows, "Offset (row) out of bounds")
if self.grid.first![offset] != nil {
if (!push) {
return false
}
self.shiftRight(row: offset)
}
self.grid[0][offset] = piece
return true
case .Bottom:
precondition(offset < self.columns, "Offset (column) out of bounds")
if self.grid[offset].last! != nil {
if (!push) {
return false
}
Board.shiftUp(column: &self.grid[offset])
}
let lastIndex = self.grid[offset].count - 1
self.grid[offset][lastIndex] = piece
return true
case .Right:
precondition(offset < self.rows, "Offset (row) out of bounds")
if self.grid.last![offset] != nil {
if (!push) {
return false
}
self.shiftLeft(row: offset)
}
self.grid[self.columns - 1][offset] = piece
return true
}
}
private static func shiftDown(column: inout [Piece?]) {
for i in (1..<column.count).reversed() {
column[i] = column[i - 1]
}
}
private static func shiftUp(column: inout [Piece?]) {
for i in 0..<(column.count - 1) {
column[i] = column[i + 1]
}
}
private mutating func shiftLeft(row: Int) {
for i in 0..<(grid.count - 1) {
self.grid[i][row] = self.grid[i + 1][row]
}
}
private mutating func shiftRight(row: Int) {
for i in 1..<grid.count {
self.grid[i - 1][row] = self.grid[i][row]
}
}
}