Skip to content

Instantly share code, notes, and snippets.

@dehlen

dehlen/GridPlayground.swift Secret

Created Nov 5, 2018
Embed
What would you like to do?
import UIKit
struct Array2D<T> {
let columns: Int
let rows: Int
fileprivate var array: [T]
init(rows: Int, columns: Int, initialValue: T) {
self.rows = rows
self.columns = columns
array = .init(repeating: initialValue, count: rows * columns)
}
subscript(row: Int, column: Int) -> T {
get {
precondition(row < rows, "Row \(row) Index is out of range. Array<T>(columns: \(columns), rows:\(rows))")
precondition(column < columns, "Column \(column) Index is out of range. Array<T>(columns: \(columns), rows:\(rows))")
return array[row*columns + column]
}
set {
precondition(row < rows, "Row \(row) Index is out of range. Array<T>(columns: \(columns), rows:\(rows))")
precondition(column < columns, "Column \(column) Index is out of range. Array<T>(columns: \(columns), rows:\(rows))")
array[row*columns + column] = newValue
}
}
}
struct WalkingIncrement {
let dx: Int
let dy: Int
}
struct GameBoardPosition: Equatable {
var row: Int
var column: Int
func walk(increment: WalkingIncrement) -> GameBoardPosition {
return GameBoardPosition(row: row + increment.dx, column: column + increment.dy)
}
}
struct GameTile {
var type: GameTileType = .empty
}
enum GameTileType {
case white
case black
case gold
case empty
}
protocol GameMove {
var start: GameBoardPosition? { get }
var end: GameBoardPosition { get }
init(start: GameBoardPosition?, end: GameBoardPosition)
}
protocol GameBoard {
var rows: Int { get }
var columns: Int { get }
var tiles: Array2D<GameTile> { get }
func tileType(at position: GameBoardPosition) -> GameTileType
}
private func isValidHorizontal(move: GameMove, board: GameBoard) -> Bool {
guard let start = move.start else { return false }
guard start.row == move.end.row else { return false }
var from: Int = start.column
var to: Int = move.end.column + 1
if start.column < move.end.column {
from += 1
} else {
from = move.end.column
to = start.column
}
for column in from..<to {
if board.tileType(at: GameBoardPosition(row: start.row, column: column)) != .empty {
return false
}
}
return true
}
private func isValidVertical(move: GameMove, board: GameBoard) -> Bool {
guard let start = move.start else { return false }
guard start.column == move.end.column else { return false }
var from: Int = start.row
var to: Int = move.end.row + 1
if start.row < move.end.row {
from += 1
} else {
from = move.end.row
to = start.row
}
for row in from..<to {
if board.tileType(at: GameBoardPosition(row: row, column: start.column)) != .empty {
return false
}
}
return true
}
private func isValid(position: GameBoardPosition, on board: GameBoard) -> Bool {
return position.row >= 0 && position.row <= board.rows - 1 && position.column >= 0 && position.column <= board.columns - 1
}
private func isValidDiagonal(move: GameMove, board: GameBoard) -> Bool {
guard let start = move.start else { return false }
var currentPosition = start
var walkingIncrement: WalkingIncrement!
if start.row == 0 && start.column == 0 {
walkingIncrement = WalkingIncrement(dx: 1, dy: 1)
} else if start.row == 0 && start.column == board.columns - 1 {
walkingIncrement = WalkingIncrement(dx: 1, dy: -1)
} else if start.row == board.rows - 1 && start.column == 0 {
walkingIncrement = WalkingIncrement(dx: -1, dy: 1)
} else if start.row == board.rows - 1 && start.column == board.columns - 1 {
walkingIncrement = WalkingIncrement(dx: -1, dy: -1)
} else {
return false
}
currentPosition = currentPosition.walk(increment: walkingIncrement)
while(isValid(position: currentPosition, on: board) && currentPosition != move.end) {
if board.tileType(at: currentPosition) != .empty {
return false
}
currentPosition = currentPosition.walk(increment: walkingIncrement)
}
return true
}
struct SampleBoard: GameBoard {
var rows: Int = 10
var columns: Int = 10
var tiles: Array2D<GameTile>
init() {
self.tiles = Array2D<GameTile>(rows: rows, columns: columns, initialValue: GameTile())
}
func tileType(at position: GameBoardPosition) -> GameTileType {
return self.tiles[position.row, position.column].type
}
}
struct SampleGameMove: GameMove {
var start: GameBoardPosition?
var end: GameBoardPosition
init(start: GameBoardPosition?, end: GameBoardPosition) {
self.start = start
self.end = end
}
}
var sampleBoard = SampleBoard()
sampleBoard.tiles[0, 0] = GameTile(type: .white)
sampleBoard.tiles[4, 4] = GameTile(type: .gold)
isValidDiagonal(move: SampleGameMove(start: GameBoardPosition(row: 0, column: 0), end: GameBoardPosition(row: 5, column: 5)), board: sampleBoard) //false
isValidDiagonal(move: SampleGameMove(start: GameBoardPosition(row: 0, column: 0), end: GameBoardPosition(row: 3, column: 3)), board: sampleBoard) //true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment