From 57283d55e52a8068bfb025233adc3d2a6d6b5cc3 Mon Sep 17 00:00:00 2001 From: Adam BONAFOS Date: Mon, 3 Feb 2025 12:06:13 +0100 Subject: [PATCH] first game in main :tada: --- Connect4.xcworkspace/contents.xcworkspacedata | 2 +- .../Connect4_CLI.xcodeproj/project.pbxproj | 22 ++++++++++++++-- Connect4_CLI/Connect4_CLI/main.swift | 26 ++++++++++++++++++- Model/Sources/Model/Board.swift | 2 +- Model/Sources/Model/Connect4Rules.swift | 8 +++--- Model/Sources/Model/Move.swift | 18 +++++++++++++ Model/Sources/Model/Player/HumanPlayer.swift | 12 ++++----- Model/Sources/Model/Player/Player.swift | 8 +++--- Model/Sources/Model/Player/RandomPlayer.swift | 4 +-- Model/Sources/Model/Rules.swift | 5 ++-- Model/Sources/Model/TicTacToeRules.swift | 10 +++---- 11 files changed, 89 insertions(+), 28 deletions(-) create mode 100644 Model/Sources/Model/Move.swift diff --git a/Connect4.xcworkspace/contents.xcworkspacedata b/Connect4.xcworkspace/contents.xcworkspacedata index 2c5a92b..b2758ea 100644 --- a/Connect4.xcworkspace/contents.xcworkspacedata +++ b/Connect4.xcworkspace/contents.xcworkspacedata @@ -5,6 +5,6 @@ location = "group:Model"> + location = "group:Connect4_CLI/Connect4_CLI.xcodeproj"> diff --git a/Connect4_CLI/Connect4_CLI.xcodeproj/project.pbxproj b/Connect4_CLI/Connect4_CLI.xcodeproj/project.pbxproj index 5f240b3..7a7536a 100644 --- a/Connect4_CLI/Connect4_CLI.xcodeproj/project.pbxproj +++ b/Connect4_CLI/Connect4_CLI.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ 90BAEDC82D34F75500C6B480 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90BAEDC72D34F75500C6B480 /* main.swift */; }; + 90C8428D2D50D02200DDFF08 /* Model in Frameworks */ = {isa = PBXBuildFile; productRef = 90C8428C2D50D02200DDFF08 /* Model */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -25,7 +26,6 @@ /* Begin PBXFileReference section */ 90BAEDC42D34F75500C6B480 /* Connect4_CLI */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Connect4_CLI; sourceTree = BUILT_PRODUCTS_DIR; }; 90BAEDC72D34F75500C6B480 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; - 90BAEDCE2D34F78600C6B480 /* Model */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Model; path = ../Model; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -33,6 +33,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 90C8428D2D50D02200DDFF08 /* Model in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -42,9 +43,9 @@ 90BAEDBB2D34F75500C6B480 = { isa = PBXGroup; children = ( - 90BAEDCE2D34F78600C6B480 /* Model */, 90BAEDC62D34F75500C6B480 /* Connect4_CLI */, 90BAEDC52D34F75500C6B480 /* Products */, + 90C8428B2D50D02200DDFF08 /* Frameworks */, ); sourceTree = ""; }; @@ -64,6 +65,13 @@ path = Connect4_CLI; sourceTree = ""; }; + 90C8428B2D50D02200DDFF08 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -80,6 +88,9 @@ dependencies = ( ); name = Connect4_CLI; + packageProductDependencies = ( + 90C8428C2D50D02200DDFF08 /* Model */, + ); productName = Connect4_CLI; productReference = 90BAEDC42D34F75500C6B480 /* Connect4_CLI */; productType = "com.apple.product-type.tool"; @@ -282,6 +293,13 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + +/* Begin XCSwiftPackageProductDependency section */ + 90C8428C2D50D02200DDFF08 /* Model */ = { + isa = XCSwiftPackageProductDependency; + productName = Model; + }; +/* End XCSwiftPackageProductDependency section */ }; rootObject = 90BAEDBC2D34F75500C6B480 /* Project object */; } diff --git a/Connect4_CLI/Connect4_CLI/main.swift b/Connect4_CLI/Connect4_CLI/main.swift index 80cdedc..711b143 100644 --- a/Connect4_CLI/Connect4_CLI/main.swift +++ b/Connect4_CLI/Connect4_CLI/main.swift @@ -6,6 +6,30 @@ // import Foundation +import Model -print("Hello, World!") +print("Connect4") +func read(question: String) -> String { + print(question) + let answer = readLine() + if let answer { + return answer + } else { + return "" + } +} + +var board = Board(rowsNb: 6, columnsNb: 7) +var rules = Connect4Rules(piecesToAlign: 4) +var player1: Player = HumanPlayer(rules: rules, color: .red, name: "player1", CLI: read) +var player2: Player = HumanPlayer(rules: rules, color: .yellow, name: "player2", CLI: read) + +while rules.isGameOver(board: board).0 != true { + var move = player1.play() + while rules.possibleMoves(board: board).contains(move) != true { + print("Move invalide en choisir un autre") + move = player1.play() + } + board[move.row, move.column] = player1.color +} diff --git a/Model/Sources/Model/Board.swift b/Model/Sources/Model/Board.swift index 8fb3e58..67e07e4 100644 --- a/Model/Sources/Model/Board.swift +++ b/Model/Sources/Model/Board.swift @@ -18,7 +18,7 @@ public struct Board { grid = Array(repeating: Array(repeating: Token.empty, count: columnsNb), count: rowsNb) } - subscript(row: Int, column: Int) -> Token { + public subscript(row: Int, column: Int) -> Token { get { guard row >= 0 && row < rowNb && column >= 0 && column < columnNb else { fatalError("Out of board") diff --git a/Model/Sources/Model/Connect4Rules.swift b/Model/Sources/Model/Connect4Rules.swift index 8fb70f8..11f0c70 100644 --- a/Model/Sources/Model/Connect4Rules.swift +++ b/Model/Sources/Model/Connect4Rules.swift @@ -96,14 +96,14 @@ public struct Connect4Rules : Rules { return true } - func possibleMoves(board: Board) -> [(row: Int, column: Int)] { - var possibleMoves: [(Int, Int)] = [] + public func possibleMoves(board: Board) -> [Move] { + var possibleMoves: [Move] = [] for column in 0.. String)? + private var CLI: ((String) -> String)? // Initialisation avec la closure CLI - init(CLI: @escaping (String) -> String) { + public init(rules: Rules, color: Token, name: String, CLI: @escaping (String) -> String) { self.CLI = CLI - super.init() + super.init(rules: rules, color: color, name: name) } - override func play() -> (row: Int, column: Int) { + public override func play() -> Move { // Demande la colonne à l'utilisateur let columnInput = CLI!("Entrez le numéro de la colonne : ") guard let column = Int(columnInput) else { @@ -27,6 +27,6 @@ class HumanPlayer : Player { guard let row = Int(rowInput) else { fatalError("Entrée invalide pour la ligne.") } - return (row, column) + return Move(row: row, column: column) } } diff --git a/Model/Sources/Model/Player/Player.swift b/Model/Sources/Model/Player/Player.swift index e5a8162..c051a71 100644 --- a/Model/Sources/Model/Player/Player.swift +++ b/Model/Sources/Model/Player/Player.swift @@ -6,16 +6,16 @@ // import Foundation -class Player { +public class Player { var name: String - var color: Token + public let color: Token var rules: Rules - init(rules: Rules, color: Token, name: String){ + public init(rules: Rules, color: Token, name: String){ self.name = name self.color = color self.rules = rules } - func play() -> (row: Int, column: Int){ + public func play() -> Move { fatalError("Must override in subclass") } } diff --git a/Model/Sources/Model/Player/RandomPlayer.swift b/Model/Sources/Model/Player/RandomPlayer.swift index f72e756..afa14af 100644 --- a/Model/Sources/Model/Player/RandomPlayer.swift +++ b/Model/Sources/Model/Player/RandomPlayer.swift @@ -7,7 +7,7 @@ import Foundation class RandomPlayer : AIPlayer { - override func play() -> (row: Int, column: Int) { - return (0, 0) + override func play() -> Move { + return Move(row: 0, column: 0) } } diff --git a/Model/Sources/Model/Rules.swift b/Model/Sources/Model/Rules.swift index f48b4d2..8465292 100644 --- a/Model/Sources/Model/Rules.swift +++ b/Model/Sources/Model/Rules.swift @@ -6,9 +6,10 @@ // import Foundation -protocol Rules { + +public protocol Rules { func add(board: inout Board, position pos: (row: Int, column: Int), token: Token) -> Bool func isGameOver(board: Board) -> (result: Bool, winner: Token) - func possibleMoves(board: Board) -> [(row: Int, column: Int)] + func possibleMoves(board: Board) -> [Move] } diff --git a/Model/Sources/Model/TicTacToeRules.swift b/Model/Sources/Model/TicTacToeRules.swift index 4a9fb06..28040b4 100644 --- a/Model/Sources/Model/TicTacToeRules.swift +++ b/Model/Sources/Model/TicTacToeRules.swift @@ -8,13 +8,13 @@ import Foundation public struct TicTacToeRules: Rules { - func possibleMoves(board: Board) -> [(row: Int, column: Int)] { - var possibleMoves: [(Int, Int)] = [] + public func possibleMoves(board: Board) -> [Move] { + var possibleMoves: [Move] = [] for column in 0.. Bool { + public func add(board: inout Board, position pos: (row: Int, column: Int), token: Token) -> Bool { if board[pos.0, pos.1] == .empty { board[pos.0, pos.1] = token return true @@ -30,7 +30,7 @@ public struct TicTacToeRules: Rules { return false } - func isGameOver(board: Board) -> (result: Bool, winner: Token) { + public func isGameOver(board: Board) -> (result: Bool, winner: Token) { // Need to be complete // TODO return (false, Token.empty)