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.
144 lines
3.9 KiB
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]
|
|
}
|
|
}
|
|
}
|