From 794f5171c62f182f4ef50f7830ac190037df267d Mon Sep 17 00:00:00 2001 From: "louis.dufour" Date: Tue, 6 Feb 2024 19:46:49 +0100 Subject: [PATCH] Update(Tp5): Cela compile --- DouShouQiConsole/DouShouQiConsole/main.swift | 72 ++++++++++++++++++-- Model/Sources/Model/Enum/GameError.swift | 1 + Model/Sources/Model/Game.swift | 17 +++-- Model/Sources/Model/HumanPlayer.swift | 21 +++++- Model/Sources/Model/Interface/Rules.swift | 3 + Model/Sources/Model/Player.swift | 7 +- Model/Sources/Model/RandomPlayer.swift | 2 +- Model/Sources/Model/VerySimpleRules.swift | 15 ++++ 8 files changed, 120 insertions(+), 18 deletions(-) diff --git a/DouShouQiConsole/DouShouQiConsole/main.swift b/DouShouQiConsole/DouShouQiConsole/main.swift index 1b7749b..5c44850 100644 --- a/DouShouQiConsole/DouShouQiConsole/main.swift +++ b/DouShouQiConsole/DouShouQiConsole/main.swift @@ -92,21 +92,85 @@ if var board = Board(withGrid: initialBoardConfiguration) { print("Erreur lors de l'initialisation du plateau de jeu.") } +// Création des joueurs +let player1 = HumanPlayer(name: "Joueur 1", id: .player1) { board, rules in + // Ici, vous pourriez implémenter une logique pour lire le mouvement du joueur depuis la console. + // Cet exemple ne fournit pas une implémentation fonctionnelle pour la saisie utilisateur. + // Retournez un mouvement valide ou nil si vous voulez simuler l'interaction. + return nil +} +let player2 = RandomPlayer(withName: "IA", andId: .player2) +// Vérification que les joueurs sont correctement créés (Optional Binding) +if let player1 = player1, let player2 = player2 { + // Création des règles + let rules = VerySimpleRules() + + // Création du plateau initial + let board = VerySimpleRules.createBoard() + + // Configuration et démarrage du jeu + var game = Game(withRules: rules, andPlayer1: player1, andPlayer2: player2) + // Configuration des callbacks pour la console + game.onStart = { + print(""" + ************************************** + ==>> GAME STARTS! <<== + ************************************** + \(board) + """) + } + + game.onNextPlayer = { (player:Player) in + print(""" + ************************************** + \(player.name), it's your turn! + ************************************** + \(board) + """) + } + + game.onMoveChosen = { (move:Move) in + print("Move chosen: \(move)") + } + + game.onInvalidMove = { (error:GameError) in + print("Invalid move due to \(error). Please try again.") + } + + game.onBoardChanged = { + print("Board has changed.\n\(board)") + } + + game.onGameOver = { (winner: Player?) in + print("**************************************") + print("Game Over!!!") + if let winner = winner { + print("And the winner is... \(winner.name)!") + print(winner.id == .player1 ? "Congratulations!" : "Better luck next time!") + } else { + print("It's a draw!") + } + print("**************************************") + } + // Démarrer le jeu + game.start() +} else { + print("Erreur lors de la création des joueurs.") +} + + +/* // Création des règles et du plateau initial var rules = VerySimpleRules() var board = VerySimpleRules.createBoard() - -/* // Simulation du mouvement sur le plateau if let piece = oldBoard.grid[move.rowOrigin][move.columnOrigin].piece { newBoard.grid[move.rowDestination][move.columnDestination].piece = piece newBoard.grid[move.rowOrigin][move.columnOrigin].piece = nil } -*/ -/* // Création des joueurs let humanPlayer = HumanPlayer(name: "Joueur Humain", id: .player1) { board, rules in // Logique pour permettre à l'utilisateur de choisir un mouvement diff --git a/Model/Sources/Model/Enum/GameError.swift b/Model/Sources/Model/Enum/GameError.swift index 89e80e2..9bee76c 100644 --- a/Model/Sources/Model/Enum/GameError.swift +++ b/Model/Sources/Model/Enum/GameError.swift @@ -11,4 +11,5 @@ public enum GameError: Error { case nextPlayerError case badPlayerId(String) case invalidMove + case unknownError } diff --git a/Model/Sources/Model/Game.swift b/Model/Sources/Model/Game.swift index 05ecddb..63b92e7 100644 --- a/Model/Sources/Model/Game.swift +++ b/Model/Sources/Model/Game.swift @@ -20,11 +20,13 @@ public struct Game { public init(withRules rules: Rules, andPlayer1 player1: Player, andPlayer2 player2: Player) { self.rules = rules - self.board = Board() // Assumer une initialisation appropriée + // Utilisation de la méthode statique de VerySimpleRules pour créer le plateau initial. + self.board = VerySimpleRules.createBoard() self.players = [player1, player2] } - public func start() { + // Marquage de la fonction comme mutating permet de modifier les propriétés de la structure. + public mutating func start() { onStart?() var currentPlayerIndex = 0 var gameOver = false @@ -34,15 +36,18 @@ public struct Game { onNextPlayer?(currentPlayer) do { - guard let move = currentPlayer.chooseMove(in: board, with: rules) else { + guard let move = currentPlayer.chooseMove(board: board, rules: rules as! VerySimpleRules) else { throw GameError.invalidMove } onMoveChosen?(move) - try rules.apply(move, to: &board) + // Essayez d'appliquer le mouvement et de mettre à jour le plateau + try rules.apply(move: move, to: &board) onBoardChanged?() - if rules.isGameOver(board) { + // Vérifiez si le jeu est terminé après le mouvement + let gameResult = rules.isGameOver(board: board, lastMove: move) + if gameResult.0 { gameOver = true onGameOver?(currentPlayer) } @@ -50,7 +55,7 @@ public struct Game { onError?(error) } catch { // Gérer d'autres types d'erreurs si nécessaire - onError?(.nextPlayerError) // Utiliser une erreur générique ou logique spécifique + onError?(.unknownError) // Assurez-vous que cette erreur est ajoutée à GameError si ce n'est pas déjà fait } currentPlayerIndex = (currentPlayerIndex + 1) % players.count diff --git a/Model/Sources/Model/HumanPlayer.swift b/Model/Sources/Model/HumanPlayer.swift index 7200f5b..100a6cb 100644 --- a/Model/Sources/Model/HumanPlayer.swift +++ b/Model/Sources/Model/HumanPlayer.swift @@ -15,7 +15,22 @@ public class HumanPlayer: Player { super.init(name: name, id: id) } - public override func chooseMove(board: Board, rules: VerySimpleRules) -> Move? { - return inputMethod(board, rules) // Utilise la méthode de saisie injectée pour obtenir le mouvement - } + public override func chooseMove(board: Board, rules: Rules) -> Move? { + print("Votre tour, \(name). Saisissez votre mouvement (format attendu : 'rowOrigin columnOrigin rowDestination columnDestination') :") + + if let input = readLine() { + let components = input.split(separator: " ").map { String($0) } + if components.count == 4, + let rowOrigin = Int(components[0]), + let columnOrigin = Int(components[1]), + let rowDestination = Int(components[2]), + let columnDestination = Int(components[3]), + rules.isMoveValid(board: board, row: rowOrigin, column: columnOrigin, rowArrived: rowDestination, columnArrived: columnDestination) { + return Move(owner: self.id, rowOrigin: rowOrigin, columnOrigin: columnOrigin, rowDestination: rowDestination, columnDestination: columnDestination) + } else { + print("Mouvement invalide. Veuillez réessayer.") + } + } + return nil + } } diff --git a/Model/Sources/Model/Interface/Rules.swift b/Model/Sources/Model/Interface/Rules.swift index 19ceba1..66715db 100644 --- a/Model/Sources/Model/Interface/Rules.swift +++ b/Model/Sources/Model/Interface/Rules.swift @@ -25,6 +25,9 @@ public protocol Rules { func isMoveValid( board: Board, row: Int, column: Int, rowArrived: Int, columnArrived: Int) -> Bool func isMoveValid( board: Board, move: Move) -> Bool + + mutating func apply(move: Move, to board: inout Board) throws + func isGameOver( board: Board, lastMove: Move) -> (Bool, Result) // permet de stocker le coût qui a été fait. (playedMove) diff --git a/Model/Sources/Model/Player.swift b/Model/Sources/Model/Player.swift index 94c9791..a986f2d 100644 --- a/Model/Sources/Model/Player.swift +++ b/Model/Sources/Model/Player.swift @@ -18,9 +18,8 @@ public class Player { } // Méthode chooseMove qui doit être surchargée dans les classes dérivées. - public func chooseMove(board: Board, rules: VerySimpleRules) -> Move? { - // Dans la classe de base, cette méthode ne fait rien. - // Les classes dérivées implémenteront leur propre logique. - return nil + public func chooseMove(board: Board, rules: Rules) -> Move? { + // Méthode devant être remplacée par des sous-classes + fatalError("Cette méthode doit être implémentée par des sous-classes.") } } diff --git a/Model/Sources/Model/RandomPlayer.swift b/Model/Sources/Model/RandomPlayer.swift index 28a19dc..2fd8cd3 100644 --- a/Model/Sources/Model/RandomPlayer.swift +++ b/Model/Sources/Model/RandomPlayer.swift @@ -14,7 +14,7 @@ public class RandomPlayer: Player { super.init(name: name, id: id) } - public override func chooseMove(board: Board, rules: VerySimpleRules) -> Move? { + public override func chooseMove(board: Board, rules: Rules) -> Move? { let validMoves = rules.getMoves(board: board, owner: self.id) return validMoves.randomElement() // Sélectionne un mouvement aléatoire parmi les mouvements valides } diff --git a/Model/Sources/Model/VerySimpleRules.swift b/Model/Sources/Model/VerySimpleRules.swift index eae7be5..3a91c49 100644 --- a/Model/Sources/Model/VerySimpleRules.swift +++ b/Model/Sources/Model/VerySimpleRules.swift @@ -141,6 +141,21 @@ public struct VerySimpleRules: Rules { return isMoveValid(board: board, move: move) } + public mutating func apply(move: Move, to board: inout Board) throws { + // Vérifier si le mouvement est valide + guard isMoveValid(board: board, move: move) else { + throw GameError.invalidMove + } + + // Effectuer le mouvement: supprimer la pièce de la cellule d'origine et l'ajouter à la cellule de destination + board.removePiece(atRow: move.rowOrigin, andColumn: move.columnOrigin) + let piece = board.getCell(atRow: move.rowOrigin, column: move.columnOrigin)?.piece + _ = board.insert(piece: piece!, atRow: move.rowDestination, andColumn: move.columnDestination) + + // Mettre à jour l'historique des mouvements + historic.append(move) + } + public func isGameOver(board: Board, lastMove: Move) -> (Bool, Result) { // Vérifier si la tannière de l'adversaire a été atteinte var opponent: Owner