From 55cedeb7b00fa39c308219b75bb803ef082cfdea Mon Sep 17 00:00:00 2001 From: Mathieu GROUSSEAU Date: Thu, 16 Jan 2025 22:42:30 +0100 Subject: [PATCH] Work on board --- .../contents.xcworkspacedata | 2 +- CustomTypes/.gitignore | 8 + CustomTypes/Package.swift | 23 +++ .../Sources/CustomTypes/CustomTypes.swift | 2 + .../CustomTypesTests/CustomTypesTests.swift | 12 ++ Model/Sources/Model/Board.swift | 147 +++++++++++++++++- Model/Sources/Model/Side.swift | 3 + 7 files changed, 191 insertions(+), 6 deletions(-) create mode 100644 CustomTypes/.gitignore create mode 100644 CustomTypes/Package.swift create mode 100644 CustomTypes/Sources/CustomTypes/CustomTypes.swift create mode 100644 CustomTypes/Tests/CustomTypesTests/CustomTypesTests.swift create mode 100644 Model/Sources/Model/Side.swift diff --git a/Connect 4.xcworkspace/contents.xcworkspacedata b/Connect 4.xcworkspace/contents.xcworkspacedata index 4323c1d..7d0dd6c 100644 --- a/Connect 4.xcworkspace/contents.xcworkspacedata +++ b/Connect 4.xcworkspace/contents.xcworkspacedata @@ -2,7 +2,7 @@ + location = "group:CustomTypes"> diff --git a/CustomTypes/.gitignore b/CustomTypes/.gitignore new file mode 100644 index 0000000..0023a53 --- /dev/null +++ b/CustomTypes/.gitignore @@ -0,0 +1,8 @@ +.DS_Store +/.build +/Packages +xcuserdata/ +DerivedData/ +.swiftpm/configuration/registries.json +.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata +.netrc diff --git a/CustomTypes/Package.swift b/CustomTypes/Package.swift new file mode 100644 index 0000000..3f2a492 --- /dev/null +++ b/CustomTypes/Package.swift @@ -0,0 +1,23 @@ +// swift-tools-version: 5.10 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "CustomTypes", + products: [ + // Products define the executables and libraries a package produces, making them visible to other packages. + .library( + name: "CustomTypes", + targets: ["CustomTypes"]), + ], + targets: [ + // Targets are the basic building blocks of a package, defining a module or a test suite. + // Targets can depend on other targets in this package and products from dependencies. + .target( + name: "CustomTypes"), + .testTarget( + name: "CustomTypesTests", + dependencies: ["CustomTypes"]), + ] +) diff --git a/CustomTypes/Sources/CustomTypes/CustomTypes.swift b/CustomTypes/Sources/CustomTypes/CustomTypes.swift new file mode 100644 index 0000000..08b22b8 --- /dev/null +++ b/CustomTypes/Sources/CustomTypes/CustomTypes.swift @@ -0,0 +1,2 @@ +// The Swift Programming Language +// https://docs.swift.org/swift-book diff --git a/CustomTypes/Tests/CustomTypesTests/CustomTypesTests.swift b/CustomTypes/Tests/CustomTypesTests/CustomTypesTests.swift new file mode 100644 index 0000000..daca8e3 --- /dev/null +++ b/CustomTypes/Tests/CustomTypesTests/CustomTypesTests.swift @@ -0,0 +1,12 @@ +import XCTest +@testable import CustomTypes + +final class CustomTypesTests: XCTestCase { + func testExample() throws { + // XCTest Documentation + // https://developer.apple.com/documentation/xctest + + // Defining Test Cases and Test Methods + // https://developer.apple.com/documentation/xctest/defining_test_cases_and_test_methods + } +} diff --git a/Model/Sources/Model/Board.swift b/Model/Sources/Model/Board.swift index bbefdc2..18dc57b 100644 --- a/Model/Sources/Model/Board.swift +++ b/Model/Sources/Model/Board.swift @@ -1,14 +1,151 @@ public struct Board { var grid: [[Piece?]] + + public var width: Int { return grid.count } + public var height: Int { return grid.first!.count } - public init(width: Int, height: Int) throws { - // guard width > 0, height > 0 else { - // // TODO: Swift std error? - // } + public init?(width: Int, height: Int) { self.init(grid: Array(repeating: Array(repeating: nil, count: height), count: width)) } - public init(grid: [[Piece?]]) { + 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.width && row >= 0 && row < self.height, "Coordinates out of bounds") + } + + 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() -> Int { + var count = 0; + + for column in grid { + for piece in column { + if piece != nil { + count += 1 + } + } + } + + return count + } + + public func countPieces(of_type type: Piece) -> Int { + var count = 0 + + for column in grid { + for piece in column { + if piece == type { + count += 1 + } + } + } + + return count + } + + 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.width, "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.height, "Offset (row) out of bounds") + + if self.grid.first![offset] != nil { + if (!push) { + return false + } + + self.shiftLeft(row: offset) + } + + self.grid[0][offset] = piece + + return true + case .Bottom: + precondition(offset < self.width, "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.height, "Offset (row) out of bounds") + + if self.grid.last![offset] != nil { + if (!push) { + return false + } + + self.shiftLeft(row: offset) + } + + let lastIndex = self.grid[offset].count - 1 + self.grid[offset][lastIndex] = piece + + return true + } + } + + private static func shiftDown(column: inout [Piece?]) { + for i in (1..