projectswift

master
etudiant 2 years ago
parent 0100e7c2ef
commit e7b0645c30

@ -1 +0,0 @@
Subproject commit bd4c7ffd777bbfdebec09917d66c818c6ed4f873

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

@ -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)")
}

@ -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)
}
}

@ -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..<nbRows {
// si la cellule est vide, retourne false
if grid[row][column] == nil {
return false
}
}
// si toutes les cellules sont pleines, retourne true
return true
}
private mutating func insertPiece(id:Int, row:Int, column:Int) -> 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..<nbRows ).reversed() {
// Si la ligne est inférieure à 0, retourner une erreur "colonne pleine"
if row < 0 {
return .failed(.columnFull)
} // Appeler la fonction `insertPiece` avec les arguments `id`, `row`, et `column`
result = insertPiece(id: id, row: row, column: column)
// Vérifier le résultat de l'insertion
switch result {
// Si l'insertion a réussi, retourner `.ok`
case .ok:
return .ok
// Sinon, continuer la boucle
default:
break
}
}
return .failed(.unknown)
}
public mutating func removePiece(row:Int, column:Int) -> 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..<nbRows {
for c in 0..<nbColumns {
grid[r][c] = nil
}
}
}
}

@ -0,0 +1,20 @@
//
// File.swift
//
//
// Created by etudiant on 09/02/2023.
//
import Foundation
public enum BoardResult : Equatable{
case unknown
case ok
case failed(FailedReason)
}
public enum FailedReason {
case unknown
case columnFull
case boardFull
case outOfBound
}

@ -0,0 +1,124 @@
//
// File.swift
//
//
// Created by etudiant on 09/02/2023.
//
import Foundation
public class ClassicRules : Rule {
private let board: Board
private let Minnbrcoln = 4
private let MinnbrRow = 4
private var isOver = false
public init?(withBoard board: Board){
guard board.nbColumns >= 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..<board.nbRows {
// Si une case dans la colonne actuelle est remplie, enregistre les coordonnées (ligne, colonne) et l'identifiant de la pièce.
if let idCase = grid[i][column] {
y = i
id = idCase
break
}
}
// Renvoie les coordonnées (ligne, colonne) et l'identifiant de la pièce.
return (y, id);
}
// Cette fonction publique `isGameOver` vérifie si la partie est terminée.
public func isGameOver() -> Bool {
isOver = true
for i in 0..<board.nbColumns {
if board.grid[0][i] == 0 {
isOver = false
break
}
}
return isOver
}
}

@ -0,0 +1,89 @@
//
// File.swift
//
//
// Created by etudiant on 09/02/2023.
//
import Foundation
public struct Game {
// La variable privée `board` représente le plateau de jeu
private var board: Board
// La variable privée `players` représente les joueurs
private var players: [Player]
private var numero: Int = 0
// La variable privée `afficheur` représente l'afficheur de messages
private var afficheur: Afficheur
private var rule: Rule
// Initialise le jeu avec un plateau donné, des joueurs donnés, des règles données et un afficheur donné
public init?(withBoard board: Board, playedBy players: [Player], withRules rule: Rule, writeOn afficheur: Afficheur) {
// Affecte les valeurs aux variables d'instance
self.board = board
self.players = players
self.afficheur = afficheur
self.rule = rule
}
// Initialise le jeu avec une grille donnée, des joueurs donnés, des règles données et un afficheur donné
public init?(withGrid grid: [[Int?]], playedBy players: [Player], withRules rule: Rule, writeOn afficheur: Afficheur) {
// Initialise un nouveau plateau avec la grille donnée
let b = Board(withGrid: grid)
// Vérifie que le plateau a bien été initialisé
guard b != nil else {
// Si ce n'est pas le cas, retourne nil
return nil
}
board = b!
self.players = players
self.afficheur = afficheur
self.rule = rule
}
// Initialise le jeu avec un nombre donné de lignes et de colonnes, des joueurs donnés, des règles données et un afficheur donné
public init?(withNbRow nbRow: Int = 6, withNbCol nbCol: Int = 7, playedBy players: [Player], withRules rule: Rule, writeOn afficheur: Afficheur) {
// On crée un plateau de jeu avec les dimensions spécifiées.
let b = Board(n1: nbRow, n2: nbCol)
// Si le plateau ne peut pas être créé, on renvoie nil.
guard b != nil else {
return nil
}
// Sinon, on définit le plateau de jeu pour l'instance actuelle de la classe Game.
board = b!
// On enregistre les joueurs qui joueront la partie.
self.players = players
// On enregistre l'afficheur qui sera utilisé pour afficher les informations sur le plateau.
self.afficheur = afficheur
// On enregistre les règles du jeu qui seront utilisées pour valider les mouvements des joueurs.
self.rule = rule;
}
// Méthode qui permet à un joueur de jouer un tour.
public mutating func tour() -> 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
}
}

@ -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()
}
}

@ -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))
}
}

@ -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()
}
}

@ -1,4 +1,4 @@
public struct HelloStruct {
public struct MyJeux {
public private(set) var text = "Hello, World!"
public init() {

@ -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
}

@ -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
}

@ -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!")
}
}

@ -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..<b.nbRows {
for c in 0..<b.nbColumns {
XCTAssertNil(b.grid[r][c])
}
}
}
}
func constructor() throws {
var n1 = -8
var n2 = 10
var b = Board(n1: n1, n2: n2)
XCTAssertNil(b?.grid)
n1 = 4
n2 = -10
b = Board(n1: n1, n2: n2)
XCTAssertNil(b?.grid)
n1 = 4
n2 = 10
b = Board(n1:n1, n2: n2)
XCTAssertNotNil(b?.grid)
XCTAssertEqual(n1, b?.nbRows)
XCTAssertEqual(n2, b?.nbColumns)
}
}

@ -1 +0,0 @@
Subproject commit 8862d6b914bebfae93ac4fe106309ca1fb496b0e
Loading…
Cancel
Save