diff --git a/Pendu.xcodeproj/project.pbxproj b/Pendu.xcodeproj/project.pbxproj index 9cef4cdf47d37dc7c6e6664713c12ac6b696e14b..1ee074526287de6dc7104bc70603caf180b34f07 100644 --- a/Pendu.xcodeproj/project.pbxproj +++ b/Pendu.xcodeproj/project.pbxproj @@ -7,7 +7,8 @@ objects = { /* Begin PBXBuildFile section */ - 157E41DB2A1D136300E6DE57 /* zadi.jpeg in Resources */ = {isa = PBXBuildFile; fileRef = 157E41DA2A1D136300E6DE57 /* zadi.jpeg */; }; + BF1D4A112A1CF23B002F97CB /* GameEngineMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5A7EC82A13BF8A00168B16 /* GameEngineMock.swift */; }; + BF1D4A122A1CF36D002F97CB /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF3C480D2A0A1FCA00CE128F /* AppDelegate.swift */; }; BF3C480E2A0A1FCA00CE128F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF3C480D2A0A1FCA00CE128F /* AppDelegate.swift */; }; BF3C48102A0A1FCA00CE128F /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF3C480F2A0A1FCA00CE128F /* SceneDelegate.swift */; }; BF3C48122A0A1FCA00CE128F /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF3C48112A0A1FCA00CE128F /* ViewController.swift */; }; @@ -19,6 +20,7 @@ BF3C48322A0A1FCD00CE128F /* PenduUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF3C48312A0A1FCD00CE128F /* PenduUITests.swift */; }; BF3C48342A0A1FCD00CE128F /* PenduUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF3C48332A0A1FCD00CE128F /* PenduUITestsLaunchTests.swift */; }; BF3C48432A0A3CFF00CE128F /* GameEngineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF3C48422A0A3CFF00CE128F /* GameEngineTests.swift */; }; + BF7F866E2A1CF44B0063A152 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF3C480D2A0A1FCA00CE128F /* AppDelegate.swift */; }; D082CCC92A0A33D600D97981 /* GameEngine.swift in Sources */ = {isa = PBXBuildFile; fileRef = D082CCC82A0A33D600D97981 /* GameEngine.swift */; }; D082CCCA2A0A33D600D97981 /* GameEngine.swift in Sources */ = {isa = PBXBuildFile; fileRef = D082CCC82A0A33D600D97981 /* GameEngine.swift */; }; D082CCCB2A0A33D600D97981 /* GameEngine.swift in Sources */ = {isa = PBXBuildFile; fileRef = D082CCC82A0A33D600D97981 /* GameEngine.swift */; }; @@ -58,6 +60,7 @@ BF3C48312A0A1FCD00CE128F /* PenduUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PenduUITests.swift; sourceTree = "<group>"; }; BF3C48332A0A1FCD00CE128F /* PenduUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PenduUITestsLaunchTests.swift; sourceTree = "<group>"; }; BF3C48422A0A3CFF00CE128F /* GameEngineTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameEngineTests.swift; sourceTree = "<group>"; }; + BF5A7EC82A13BF8A00168B16 /* GameEngineMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameEngineMock.swift; sourceTree = "<group>"; }; D082CCC82A0A33D600D97981 /* GameEngine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GameEngine.swift; sourceTree = "<group>"; }; /* End PBXFileReference section */ @@ -120,6 +123,7 @@ BF3C48162A0A1FCA00CE128F /* Pendu.xcdatamodeld */, D082CCC82A0A33D600D97981 /* GameEngine.swift */, BF3C48422A0A3CFF00CE128F /* GameEngineTests.swift */, + BF5A7EC82A13BF8A00168B16 /* GameEngineMock.swift */, ); path = Pendu; sourceTree = "<group>"; @@ -286,7 +290,9 @@ buildActionMask = 2147483647; files = ( BF3C48282A0A1FCD00CE128F /* PenduTests.swift in Sources */, + BF1D4A112A1CF23B002F97CB /* GameEngineMock.swift in Sources */, D082CCCA2A0A33D600D97981 /* GameEngine.swift in Sources */, + BF1D4A122A1CF36D002F97CB /* AppDelegate.swift in Sources */, BF3C48432A0A3CFF00CE128F /* GameEngineTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -295,6 +301,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + BF7F866E2A1CF44B0063A152 /* AppDelegate.swift in Sources */, BF3C48322A0A1FCD00CE128F /* PenduUITests.swift in Sources */, D082CCCB2A0A33D600D97981 /* GameEngine.swift in Sources */, BF3C48342A0A1FCD00CE128F /* PenduUITestsLaunchTests.swift in Sources */, diff --git a/Pendu/GameEngine.swift b/Pendu/GameEngine.swift index a11054f68a68c6e52f46f370f11dd66a1acdc3f6..e99a54aed2060e237cf16568522c31fb489b48a7 100644 --- a/Pendu/GameEngine.swift +++ b/Pendu/GameEngine.swift @@ -6,23 +6,34 @@ // import UIKit +import CoreData class GameEngine: NSObject { - private var listThemeAnimalsEasy : [String] = ["Chien", "Chat", "Lion", "Girafe", "Éléphant", "Serpent", "Oiseau", "Tigre", "Papillon", "Singe"] - private var listThemeSportsEasy : [String] = ["Football", "Basket-ball", "Tennis", "Natation", "Rugby", "Golf", "Volley-ball", "Baseball", "Athlétisme", "Boxe"] - private var listThemeFoodEasy : [String] = ["Pomme", "Banane", "Carotte", "Poisson", "Riz", "Fromage", "Pain", "Chocolat", "Fraise", "Poulet"] - private var listThemeCitiesEasy : [String] = ["Paris", "Londres", "New York", "Rome", "Tokyo", "Sydney", "Barcelone", "Berlin", "Istanbul", "Mumbai"] - private var listThemeColorsEasy : [String] = ["Rouge", "Bleu", "Vert", "Jaune", "Rose", "Violet", "Orange", "Gris", "Marron", "Noir"] + private var listThemeAnimalsEasy : [String] = ["Chien", "Chat", "Lion", "Girafe", "Éléphant", "Serpent", "Oiseau", "Tigre", "Papillon", "Singe"]; + private var listThemeSportsEasy : [String] = ["Football", "Basket-ball", "Tennis", "Natation", "Rugby", "Golf", "Volley-ball", "Baseball", "Athlétisme", "Boxe"]; + private var listThemeFoodEasy : [String] = ["Pomme", "Banane", "Carotte", "Poisson", "Riz", "Fromage", "Pain", "Chocolat", "Fraise", "Poulet"]; + private var listThemeCitiesEasy : [String] = ["Paris", "Londres", "New York", "Rome", "Tokyo", "Sydney", "Barcelone", "Berlin", "Istanbul", "Mumbai"]; + private var listThemeColorsEasy : [String] = ["Rouge", "Bleu", "Vert", "Jaune", "Rose", "Violet", "Orange", "Gris", "Marron", "Noir"]; - private var listThemeAnimalsHard : [String] = ["Chimpanzé", "Lynx", "Hippopotame", "Pélican", "Kangourou", "Anaconda", "Chimère", "Panda roux", "Calmar géant", "Ouistiti"] - private var listThemeSportsHard : [String] = ["Escrime", "Squash", "Haltérophilie", "Badminton", "Ski de fond", "Pentathlon moderne", "Canoë-kayak", "Aviron", "Patinage artistique", "Triathlon"] - private var listThemeFoodHard : [String] = ["Artichaut", "Quinoa", "Courge", "Wasabi", "Chou-fleur", "Sarrasin", "Salsifis", "Morue", "Canneberge", "Pistache"] - private var listThemeCitiesHard : [String] = ["Copenhague", "Budapest", "Dubrovnik", "Séoul", "Marrakech", "Reykjavik", "La Nouvelle-Orléans", "Bratislava", "Wellington", "Accra"] - private var listThemeColorsHard : [String] = ["Écarlate", "Azur", "Émeraude", "Safran", "Pourpre", "Indigo", "Sienne", "Cyan", "Vermillon", "Lavande"] + private var listThemeAnimalsHard : [String] = ["Chimpanzé", "Lynx", "Hippopotame", "Pélican", "Kangourou", "Anaconda", "Chimère", "Panda roux", "Calmar géant", "Ouistiti"]; + private var listThemeSportsHard : [String] = ["Escrime", "Squash", "Haltérophilie", "Badminton", "Ski de fond", "Pentathlon moderne", "Canoë-kayak", "Aviron", "Patinage artistique", "Triathlon"]; + private var listThemeFoodHard : [String] = ["Artichaut", "Quinoa", "Courge", "Wasabi", "Chou-fleur", "Sarrasin", "Salsifis", "Morue", "Canneberge", "Pistache"]; + private var listThemeCitiesHard : [String] = ["Copenhague", "Budapest", "Dubrovnik", "Séoul", "Marrakech", "Reykjavik", "La Nouvelle-Orléans", "Bratislava", "Wellington", "Accra"]; + private var listThemeColorsHard : [String] = ["Écarlate", "Azur", "Émeraude", "Safran", "Pourpre", "Indigo", "Sienne", "Cyan", "Vermillon", "Lavande"]; - private var wordToGuess : String = "" - private var attemptsRemaining : Int = 0 + private var wordToGuess : String = ""; + private var attemptsRemaining : Int = 0; + private var guessedLetters : [Character] = []; + private var lastGuessedLetterTime : Date? = nil; + private var theme : String = ""; + private var difficulty : String = ""; + private var playerName : String = ""; + private var score : Int = 0; + private var combo : Int = 0; + private var remainingLives : Int = 8; + + private var managedObjectContext: NSManagedObjectContext?; override init() { // @@ -30,6 +41,8 @@ class GameEngine: NSObject { func WordToGuess(theme: String, difficulty: String) -> String{ var word = "" + self.theme = theme; + self.difficulty = difficulty; if theme == "Animals"{ if difficulty == "Easy"{ let randomInt = Int.random(in: 0..<listThemeAnimalsEasy.count) @@ -74,31 +87,94 @@ class GameEngine: NSObject { return word } - //public func startNewGame(difficulty: String) -> Void { - //wordToGuess = WordToGuess(theme: "Animals", difficulty: "Easy") - //} - public func guessLetter(letter: Character) -> Bool { - + if(isGameOver()){ + return false; + } + + guessedLetters.append(letter); + if wordToGuess.contains(letter) { - return true - } else { - return false + combo += 1; + let dateNow = Date(); + + let maxElapsedTimeInSecondsForBonus = 100; + var elapsedTimeInSeconds = maxElapsedTimeInSecondsForBonus; // Initialisation au temps max + let baseGuessedLetterBonusPoint = 100; + let baseBonusPoint = 100; + let comboBonusPoints = 50; + var timeBonusMultiplier = 1; + + if(lastGuessedLetterTime != nil) { + elapsedTimeInSeconds = Int(dateNow.timeIntervalSince(lastGuessedLetterTime!)); + } + + switch difficulty { + case "Easy": + timeBonusMultiplier = 1; + case "Normal": + timeBonusMultiplier = 2; + case "Hard": + timeBonusMultiplier = 3; + default: + timeBonusMultiplier = 1; + } + + if(elapsedTimeInSeconds > maxElapsedTimeInSecondsForBonus) { + score += baseGuessedLetterBonusPoint; + } else if(elapsedTimeInSeconds < 10) { + score += baseGuessedLetterBonusPoint + baseBonusPoint * timeBonusMultiplier; + } else { + score += baseGuessedLetterBonusPoint + (baseBonusPoint * (elapsedTimeInSeconds / maxElapsedTimeInSecondsForBonus)); + } + if (combo > 1) { + score += (combo - 1) * comboBonusPoints; + } + + lastGuessedLetterTime = Date(); + return true; } - + + remainingLives -= 1; + combo = 0; + lastGuessedLetterTime = nil; + return false; } public func isGameOver() -> Bool { - // Vérification si le jeu est terminé - return false; + if(remainingLives > 0) { + return false; + } + return true; } - public func isLetterGuesses(letter: Character) -> Bool { + public func isLetterGuessed(letter: Character) -> Bool { + if(guessedLetters.contains(letter)) { + return true; + } return false; } public func saveScore() -> Void { // Enregistrement du score dans la base Core Data + + // Création du gestionnaire d'objets persistants + let context: NSManagedObjectContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext; + + // Création de l'instance de l'entité CoreData + let entity = NSEntityDescription.entity(forEntityName: "Score", in: context)!; + let object = NSManagedObject(entity: entity, insertInto: context); + object.setValue(theme, forKeyPath: "categoryName"); + object.setValue(difficulty, forKeyPath: "difficulty"); + object.setValue(playerName, forKeyPath: "playerName"); + object.setValue(score, forKeyPath: "score"); + + // On enregistre + do { + try context.save(); + } catch let error as NSError { + print("Erreur lors de l'enregistrement des données : \(error), \(error.userInfo)"); + } } static func getOnlineScoreboard() -> Void { diff --git a/Pendu/GameEngineMock.swift b/Pendu/GameEngineMock.swift new file mode 100644 index 0000000000000000000000000000000000000000..2265205f82a15ea373396e5fc479f73e683b0e05 --- /dev/null +++ b/Pendu/GameEngineMock.swift @@ -0,0 +1,19 @@ +// +// GameEngineMock.swift +// Pendu +// +// Created by Sofiane Lasri-Trienpont on 16/05/2023. +// + +import UIKit + +class GameEngineMock: GameEngine { + public var wordToGuess : String = ""; + public var attemptsRemaining : Int = 0; + public var guessedLetters : [Character] = []; + public var theme : String = ""; + public var difficulty : String = ""; + public var playerName : String = ""; + public var score : Int = 0; + public var combo : Int = 0; +} diff --git a/Pendu/GameEngineTests.swift b/Pendu/GameEngineTests.swift index 867a9bd872291d200b7d8bed0327f7b4f4866e3a..2d686e6810f5920f9081450855e4ccf41f957ea9 100644 --- a/Pendu/GameEngineTests.swift +++ b/Pendu/GameEngineTests.swift @@ -28,5 +28,5 @@ class GameEngineTests: XCTestCase { let mot2 = game.WordToGuess(theme: "Sports", difficulty: "Hard") XCTAssertNotEqual(mot1, mot2) } - + } diff --git a/Pendu/Pendu.xcdatamodeld/Pendu.xcdatamodel/contents b/Pendu/Pendu.xcdatamodeld/Pendu.xcdatamodel/contents index c446d97726d6a01470796fa216f7c9176d7d3996..b13b2ba73d77d3a2042ecea1671b4756a3529846 100644 --- a/Pendu/Pendu.xcdatamodeld/Pendu.xcdatamodel/contents +++ b/Pendu/Pendu.xcdatamodeld/Pendu.xcdatamodel/contents @@ -1,12 +1,12 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="20086" systemVersion="21E258" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier=""> - <entity name="Scoreboard" representedClassName="Scoreboard" syncable="YES" codeGenerationType="class"> + <entity name="Score" representedClassName="Score" syncable="YES" codeGenerationType="class"> <attribute name="categoryName" optional="YES" attributeType="String"/> <attribute name="difficulty" optional="YES" attributeType="String"/> <attribute name="playerName" optional="YES" attributeType="String"/> <attribute name="score" optional="YES" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/> </entity> <elements> - <element name="Scoreboard" positionX="-63" positionY="-18" width="128" height="89"/> + <element name="Score" positionX="-63" positionY="-18" width="128" height="89"/> </elements> </model> \ No newline at end of file