diff --git a/Sources/CommandConsole b/Sources/CommandConsole deleted file mode 160000 index bd4c7ff..0000000 --- a/Sources/CommandConsole +++ /dev/null @@ -1 +0,0 @@ -Subproject commit bd4c7ffd777bbfdebec09917d66c818c6ed4f873 diff --git a/Sources/HelloCLT/HelloCLT.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Sources/HelloCLT/HelloCLT.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/Sources/HelloCLT/HelloCLT.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Sources/HelloCLT/HelloCLT.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Sources/HelloCLT/HelloCLT.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Sources/HelloCLT/HelloCLT.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Sources/HelloCLT/HelloCLT/main.swift b/Sources/HelloCLT/HelloCLT/main.swift index ce0a84d..5479654 100644 --- a/Sources/HelloCLT/HelloCLT/main.swift +++ b/Sources/HelloCLT/HelloCLT/main.swift @@ -1,14 +1,30 @@ // // main.swift -// HelloCLT +// MainJeux // -// Created by Marc Chevaldonné on 03/05/2022. +// Created by etudiant on 09/02/2023. // -import HelloLibrary - import Foundation -let helloStruct = HelloStruct() -print(helloStruct.text) +import MyJeux + +let lecteur = Lecteur() +let afficheur = Afficheur() +var b = Board() + +if let board = b { + let player1 = Human(nom: "Arafa", playedOn: board, readOn: lecteur) + let player2 = IA(nom: "Najlae", playedOn: board) + let rule = ClassicRules(withBoard: board) + var game = Game(withBoard: board, playedBy: [player1, player2], withRules: rule!, writeOn: afficheur) + var winner : Player? + while winner == nil && rule!.isGameOver() + { + winner = game?.tour() + } + + afficheur.afficherLigne(message: "Le gagnant est \(winner?.nom)") +} + diff --git a/Sources/HelloLibrary/Sources/HelloLibrary/Afficheur.swift b/Sources/HelloLibrary/Sources/HelloLibrary/Afficheur.swift new file mode 100644 index 0000000..1c145c4 --- /dev/null +++ b/Sources/HelloLibrary/Sources/HelloLibrary/Afficheur.swift @@ -0,0 +1,15 @@ +// +// File.swift +// +// +// Created by etudiant on 09/02/2023. +// + +import Foundation +public class Afficheur { + public init() {} + //cette Fonction affiche une ligne de message + public func afficherLigne(message msg: String){ + print(msg) + } +} diff --git a/Sources/HelloLibrary/Sources/HelloLibrary/Board.swift b/Sources/HelloLibrary/Sources/HelloLibrary/Board.swift new file mode 100644 index 0000000..6e5d131 --- /dev/null +++ b/Sources/HelloLibrary/Sources/HelloLibrary/Board.swift @@ -0,0 +1,160 @@ +// +// File.swift +// +// +// Created by etudiant on 09/02/2023. +// + +import Foundation +public struct Board: CustomStringConvertible { + // La grille du tableau qui peut contenir des valeurs nues (nil) ou des entiers (1 ou 2) + var grid: [[Int?]]; + // Le nombre de lignes dans la grille + let nbRows: Int; + // Le nombre de colonnes dans la grille + let nbColumns: Int; + // Une table de correspondance qui mappe les entiers (1 et 2) aux valeurs de chaînes "O" et "X" + private static let descriptionMapper: [Int?:String] = [nil:" ", 1:"O", 2:"X"]; + // Initialiseur qui permet de créer une grille avec le nombre de lignes et de colonnes données + public init?(n1: Int = 4, n2: Int = 5) { + // Si n1 ou n2 sont inférieurs ou égaux à 0, retournez nil + if n1 <= 0 || n2 <= 0 { + return nil + } + // Définit le nombre de lignes et de colonnes + self.nbRows = n1 + self.nbColumns = n2 + // Initialise la grille avec des valeurs nues (nil) + self.grid = Array(repeating: Array(repeating: nil, count: n2), count: n1) + } + + public init?(withGrid grid : [[Int?]]){ + // Récupère les tailles de chaque colonne dans la grille donnée + let sizes = grid.map{ return $0.count } + // Vérifie que toutes les tailles correspondent à la taille de la première colonne + let result = sizes.allSatisfy { + $0 == grid[0].count + } + // Si toutes les tailles ne correspondent pas, retournez nil + guard result else { + return nil + } + // Définit le nombre de lignes et de colonnes en fonction de la grille donnée + nbRows = grid.count + nbColumns = grid[0].count + // Utilise la grille donnée pour initialiser la grille + self.grid=grid + } + + + public var description: String { + // déclaration de la variable de sortie string qui sera retournée + var string = String() + // déclaration de la variable de sortie string qui sera retournée + for row in grid { + // ajout d'un séparateur de ligne pour séparer les lignes + string.append("| ") + // boucle pour parcourir les cellules dans la ligne actuelle + for cell in row { + // ajout de la description de la cellule dans la chaîne string. Si la cellule est vide, un espace vide est ajouté + string.append("\(String(describing: Board.descriptionMapper[cell] ?? " "))") + // ajout d'un séparateur de colonne pour séparer les cellules + string.append(" | ") + } + // ajout d'un saut de ligne pour passer à la ligne suivante + string.append("\n") + } + // ajout d'un séparateur de ligne pour séparer les lignes de la grille + string.append("|") + for _ in 0...grid.count{ + string.append("---|") + } + // ajout de l'index de colonne en dessous de la grille + string.append("\n") + + string.append("|") + for i in 0...grid.count{ + string.append(" \(i) |") + } + // retourne la chaîne string construite + return string + } + + private func isFull() -> Bool { + // boucle pour parcourir les colonnes + for column in 0...nbColumns{ + // si la colonne n'est pas pleine, retourne false + if !isColumnFull(column: column) { + return false + } + } + // si toutes les colonnes sont pleines, retourne true + return true + } + + private func isColumnFull(column: Int) -> Bool{ + for row in 0.. BoardResult { + // vérifie si la ligne et la colonne sont dans les limites de la grille + guard row >= 0 && row < nbRows && column >= 0 && column < nbColumns else { + // retourne une erreur si les coordonnées sont en dehors de la grille + return .failed(.outOfBound) + } + // vérifie si la cellule est déjà remplie + guard grid[row][column] == nil else { + return .failed(.unknown) + } + + grid[row][column] = id + return .ok + } + // Fonction pour insérer une pièce dans une colonne particulière + public mutating func insertPiece(id:Int, column:Int) -> BoardResult { + // Initialiser le résultat comme étant inconnu + var result = BoardResult.unknown + // Boucle à travers les lignes dans l'ordre inverse + for row in (0.. BoardResult { + guard row >= 0 && row < nbRows && column >= 0 && column < nbColumns else { + return .failed(.outOfBound) + } + + grid[row][column] = nil + return .ok + } + + public mutating func clearGrid(){ + for r in 0..= Minnbrcoln && board.nbRows >= MinnbrRow else { + return nil + } + self.board = board + } + // Fonction pour déterminer si une pièce a été insérée dans une colonne donnée + // et si elle a formé une combinaison gagnante. + public func isValid(column: Int) -> Int { + let grid = board.grid + var y = 0; + var id = 0 + // Appel de la fonction pour obtenir la dernière ligne et l'ID de la dernière pièce insérée dans cette colonne + (y, id) = gettheLast(column: column) + // Variables pour stocker le score actuel et la valeur de retour + var score = 0 + + // Définir les bornes pour la vérification des lignes, des colonnes et des diagonales + var minX = column - 3 + if minX < 0 { + minX = 0 + } + var maxX = column + 3 + if maxX >= board.nbColumns { + maxX = board.nbColumns - 1 + } + var minY = y - 3 + if minY < 0 { + minY = 0 + } + var maxY = y + 3 + if maxY >= board.nbRows { + maxY = board.nbRows - 1 + } + + // Vérification de la ligne horizontale + for i in minX...maxX { + if grid[y][i] == id { + score += 1 + } else { + score = 0 + } + } + if score >= 4 { return id } + + // Vérification de la colonne verticale + for i in minY...maxY { + if grid[i][column] == id { + score += 1 + } else { + score = 0 + } + } + if score >= 4 { return id } + + // Vérification de la diagonale allant du nord-ouest au sud-est + var minCoord = min(minX, minY) + var maxCoord = min(maxX, maxY) + for i in minCoord...maxCoord { + if grid[i][i] == id { + score += 1 + } else { + score = 0 + } + } + if score >= 4 { return id } + + // Vérification de la diagonale allant du nord-est au sud-ouest + minCoord = min(maxX, minY) + maxCoord = min(minX, maxY) + for i in minCoord...maxCoord { + if grid[i][i] == id { + score += 1 + } else { + score = 0 + } + } + if score >= 4 { return id } + return 0 + } + // Cette fonction privée `gettheLast` trouve la dernière case remplie dans une colonne donnée. + private func gettheLast(column: Int) -> (Int, Int) { + let grid = board.grid + var y = 0; + var id = 0 + // Boucle sur toutes les lignes de la grille. + for i in 0.. Bool { + isOver = true + for i in 0.. Player?{ + // On récupère le joueur actuel. + let player = players[numero] + // On initialise le résultat de l'insertion de la pièce sur le plateau. + var result = BoardResult.unknown + var choice = 0 + // Tant que la pièce ne peut pas être insérée sur le plateau, on demande au joueur où il souhaite insérer la pièce. + while( result != BoardResult.ok){ + afficheur.afficherLigne(message: "\nJoueur \(player.nom), ou veut tu inserer le jeton:) ?") + choice = player.playInColumn() + afficheur.afficherLigne(message: "Le nombre choisi est \(choice).") + result = board.insertPiece(id: numero + 1, column: choice) + } + // On vérifie si un joueur a gagné la partie. + let winnerId = rule.isValid(column: choice) + // Si un joueur a gagné, on affiche un message pour annoncer le gagnant et on retourne le joueur gagnant. + if winnerId != 0 { + afficheur.afficherLigne(message: "\(players[winnerId].nom) a gagné !") + return players[winnerId] + } + joueurSuivant(); + afficheur.afficherLigne(message: board.description) + return nil + } + + public mutating func joueurSuivant() { + numero = (numero + 1) % players.count + } +} diff --git a/Sources/HelloLibrary/Sources/HelloLibrary/Human.swift b/Sources/HelloLibrary/Sources/HelloLibrary/Human.swift new file mode 100644 index 0000000..7479e29 --- /dev/null +++ b/Sources/HelloLibrary/Sources/HelloLibrary/Human.swift @@ -0,0 +1,31 @@ +// +// File.swift +// +// +// Created by etudiant on 09/02/2023. +// + + +import Foundation + +// Définition de la classe "Human" qui conforme au protocole "Player" +public class Human : Player { + // Propriété : "nom" de type String, avec un getter et un setter + public var nom: String + // Propriété : "board" de type Board, avec un getter et un setter + public var board: Board + private var lecteur: Lecteur + + // Initialisation avec trois paramètres "nom", "board" et "lecteur" + public init(nom nom: String, playedOn board: Board, readOn lecteur: Lecteur){ + self.nom = nom + self.board = board + self.lecteur = lecteur + } + + public func playInColumn() -> Int { + lecteur.lireInt() + } + + +} diff --git a/Sources/HelloLibrary/Sources/HelloLibrary/IA.swift b/Sources/HelloLibrary/Sources/HelloLibrary/IA.swift new file mode 100644 index 0000000..c2b5583 --- /dev/null +++ b/Sources/HelloLibrary/Sources/HelloLibrary/IA.swift @@ -0,0 +1,26 @@ +// +// File.swift +// +// +// Created by etudiant on 09/02/2023. +// + +import Foundation +// Définition de la classe "IA" qui conforme au protocole "Player" +public class IA: Player { + // Propriété : "nom" de type String, avec un getter et un setter + public var nom: String + // Propriété : "board" de type Board, avec un getter et un setter + public var board: Board + // Initialisation avec deux paramètres "nom" et "board" + public init(nom nom: String, playedOn board: Board){ + self.nom = nom + self.board = board + } + // Fonction : "playInColumn" qui retourne un entier aléatoire compris entre 0 et "nbColumns" + public func playInColumn() -> Int { + return Int.random(in: 0..<(board.nbColumns)) + } + + +} diff --git a/Sources/HelloLibrary/Sources/HelloLibrary/Lecteur.swift b/Sources/HelloLibrary/Sources/HelloLibrary/Lecteur.swift new file mode 100644 index 0000000..64d4472 --- /dev/null +++ b/Sources/HelloLibrary/Sources/HelloLibrary/Lecteur.swift @@ -0,0 +1,29 @@ +// +// File.swift +// +// +// Created by etudiant on 09/02/2023. +// + +import Foundation +public class Lecteur { + public init() { + + } + // Lit une entrée entière de l'utilisateur et la retourne. + public func lireInt() -> Int{ + // Tente de lire une ligne de l'entrée de l'utilisateur. + if let value = readLine() { + // Convertit la chaîne en entier et la retourne. Si la conversion échoue, retourne -1. + return Int(value) ?? -1 + } else { + // Si la lecture de l'entrée échoue, retourne -1. + return -1 + } + } + // Lit une entrée de ligne de l'utilisateur et la retourne sous forme de chaîne. + public func lireLigne() -> String? { + // Lit une ligne de l'entrée de l'utilisateur et la retourne sous forme de chaîne. + return readLine() + } +} diff --git a/Sources/HelloLibrary/Sources/HelloLibrary/HelloStruct.swift b/Sources/HelloLibrary/Sources/HelloLibrary/MyJeux.swift similarity index 74% rename from Sources/HelloLibrary/Sources/HelloLibrary/HelloStruct.swift rename to Sources/HelloLibrary/Sources/HelloLibrary/MyJeux.swift index 9ebdb96..11b514d 100644 --- a/Sources/HelloLibrary/Sources/HelloLibrary/HelloStruct.swift +++ b/Sources/HelloLibrary/Sources/HelloLibrary/MyJeux.swift @@ -1,4 +1,4 @@ -public struct HelloStruct { +public struct MyJeux { public private(set) var text = "Hello, World!" public init() { diff --git a/Sources/HelloLibrary/Sources/HelloLibrary/Player.swift b/Sources/HelloLibrary/Sources/HelloLibrary/Player.swift new file mode 100644 index 0000000..054b5d5 --- /dev/null +++ b/Sources/HelloLibrary/Sources/HelloLibrary/Player.swift @@ -0,0 +1,22 @@ +// +// File.swift +// +// +// Created by etudiant on 09/02/2023. +// + +// Import the Foundation library +import Foundation + +// Define a protocol "Player" +public protocol Player { + + // Property: "nom" of type String, with both getter and setter + var nom: String { get set } + + // Property: "board" of type Board, with both getter and setter + var board: Board { get set } + + // Function: "playInColumn" returns an Int + func playInColumn() -> Int +} diff --git a/Sources/HelloLibrary/Sources/HelloLibrary/Rule.swift b/Sources/HelloLibrary/Sources/HelloLibrary/Rule.swift new file mode 100644 index 0000000..0ec614c --- /dev/null +++ b/Sources/HelloLibrary/Sources/HelloLibrary/Rule.swift @@ -0,0 +1,15 @@ +// +// File.swift +// +// +// Created by etudiant on 09/02/2023. +// + + +import Foundation + +// Pour avoir une collection de règles,la création d'une règle qui étend ce protocol, et qui contiendra une liste de rules permet de savoir les priorités des règles. +public protocol Rule { + func isValid(column: Int) -> Int + func isGameOver() -> Bool +} diff --git a/Sources/HelloLibrary/Tests/HelloLibraryTests/HelloStructTests.swift b/Sources/HelloLibrary/Tests/HelloLibraryTests/HelloStructTests.swift deleted file mode 100644 index 13ca6f5..0000000 --- a/Sources/HelloLibrary/Tests/HelloLibraryTests/HelloStructTests.swift +++ /dev/null @@ -1,11 +0,0 @@ -import XCTest -@testable import HelloLibrary - -final class HelloStructTests: XCTestCase { - func testExample() throws { - // This is an example of a functional test case. - // Use XCTAssert and related functions to verify your tests produce the correct - // results. - XCTAssertEqual(HelloStruct().text, "Hello, World!") - } -} diff --git a/Sources/HelloLibrary/Tests/HelloLibraryTests/MyJeuxTests.swift b/Sources/HelloLibrary/Tests/HelloLibraryTests/MyJeuxTests.swift new file mode 100644 index 0000000..5d41212 --- /dev/null +++ b/Sources/HelloLibrary/Tests/HelloLibraryTests/MyJeuxTests.swift @@ -0,0 +1,40 @@ +import XCTest +@testable import MyJeux + +final class MyJeuxTests: XCTestCase { + + func manipulation() { + var board = Board(n1: 4, n2: 4) + board?.insertPiece(id: 1, column: 2) + XCTAssertEqual(1, board?.grid[3][2]) + board?.removePiece(row: 3, column: 2) + XCTAssertNil(board?.grid[3][2]) + } + func clean(){ + var board = Board(withGrid: [[1,0,1],[0,1,0],[1,0,1]]) + if var b = board { + b.clearGrid() + for r in 0..