diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..25ee8133558e0a5ec26185307c044335f80b8516 Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..330d1674f347b629e102677ac03d3bc87315a55c --- /dev/null +++ b/.gitignore @@ -0,0 +1,90 @@ +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## User settings +xcuserdata/ + +## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) +*.xcscmblueprint +*.xccheckout + +## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) +build/ +DerivedData/ +*.moved-aside +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 + +## Obj-C/Swift specific +*.hmap + +## App packaging +*.ipa +*.dSYM.zip +*.dSYM + +## Playgrounds +timeline.xctimeline +playground.xcworkspace + +# Swift Package Manager +# +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +# Packages/ +# Package.pins +# Package.resolved +# *.xcodeproj +# +# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata +# hence it is not needed unless you have added a package configuration file to your project +# .swiftpm + +.build/ + +# CocoaPods +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# +# Pods/ +# +# Add this line if you want to avoid checking in source code from the Xcode workspace +# *.xcworkspace + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build/ + +# Accio dependency management +Dependencies/ +.accio/ + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. +# Instead, use fastlane to re-generate the screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/#source-control + +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots/**/*.png +fastlane/test_output + +# Code Injection +# +# After new code Injection tools there's a generated folder /iOSInjectionProject +# https://github.com/johnno1962/injectionforxcode + +iOSInjectionProject/ diff --git a/Pendu.xcodeproj/project.pbxproj b/Pendu.xcodeproj/project.pbxproj index ea68e0e4daa1bde953e74aa50c2008a5a1116724..a64ee7583a1761dd035d3b9ee3a73817afc99ce7 100644 --- a/Pendu.xcodeproj/project.pbxproj +++ b/Pendu.xcodeproj/project.pbxproj @@ -7,6 +7,8 @@ objects = { /* Begin PBXBuildFile section */ + 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 /* GameViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF3C48112A0A1FCA00CE128F /* GameViewController.swift */; }; @@ -18,6 +20,11 @@ BF3C48342A0A1FCD00CE128F /* PenduUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF3C48332A0A1FCD00CE128F /* PenduUITestsLaunchTests.swift */; }; F817CE932A13B9DD0078F0A5 /* whatever it takes.ttf in Resources */ = {isa = PBXBuildFile; fileRef = F817CE922A13B9DC0078F0A5 /* whatever it takes.ttf */; }; F8B49FB42A25E67600750A52 /* Game.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BF3C48132A0A1FCA00CE128F /* Game.storyboard */; }; + 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 */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -38,6 +45,7 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 157E41DA2A1D136300E6DE57 /* zadi.jpeg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; name = zadi.jpeg; path = ../../zadi.jpeg; sourceTree = "<group>"; }; BF3C480A2A0A1FCA00CE128F /* Pendu.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Pendu.app; sourceTree = BUILT_PRODUCTS_DIR; }; BF3C480D2A0A1FCA00CE128F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; BF3C480F2A0A1FCA00CE128F /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; }; @@ -53,6 +61,9 @@ 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>"; }; F817CE922A13B9DC0078F0A5 /* whatever it takes.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "whatever it takes.ttf"; 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 */ /* Begin PBXFrameworksBuildPhase section */ @@ -111,7 +122,11 @@ BF3C48192A0A1FCD00CE128F /* Assets.xcassets */, BF3C481B2A0A1FCD00CE128F /* LaunchScreen.storyboard */, BF3C481E2A0A1FCD00CE128F /* Info.plist */, + 157E41DA2A1D136300E6DE57 /* zadi.jpeg */, BF3C48162A0A1FCA00CE128F /* Pendu.xcdatamodeld */, + D082CCC82A0A33D600D97981 /* GameEngine.swift */, + BF3C48422A0A3CFF00CE128F /* GameEngineTests.swift */, + BF5A7EC82A13BF8A00168B16 /* GameEngineMock.swift */, ); path = Pendu; sourceTree = "<group>"; @@ -249,6 +264,8 @@ F817CE932A13B9DD0078F0A5 /* whatever it takes.ttf in Resources */, BF3C481D2A0A1FCD00CE128F /* LaunchScreen.storyboard in Resources */, BF3C481A2A0A1FCD00CE128F /* Assets.xcassets in Resources */, + 157E41DB2A1D136300E6DE57 /* zadi.jpeg in Resources */, + BF3C48152A0A1FCA00CE128F /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -274,6 +291,8 @@ buildActionMask = 2147483647; files = ( BF3C48122A0A1FCA00CE128F /* GameViewController.swift in Sources */, + D082CCC92A0A33D600D97981 /* GameEngine.swift in Sources */, + BF3C48122A0A1FCA00CE128F /* ViewController.swift in Sources */, BF3C480E2A0A1FCA00CE128F /* AppDelegate.swift in Sources */, BF3C48182A0A1FCA00CE128F /* Pendu.xcdatamodeld in Sources */, BF3C48102A0A1FCA00CE128F /* SceneDelegate.swift in Sources */, @@ -285,6 +304,10 @@ 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; }; @@ -292,7 +315,9 @@ 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 */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Pendu.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/Pendu.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000000000000000000000000000000000000..f9b0d7c5ea15f194be85eb6ee8e6721a87ff4644 --- /dev/null +++ b/Pendu.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -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>PreviewsEnabled</key> + <false/> +</dict> +</plist> diff --git a/Pendu/AppDelegate.swift b/Pendu/AppDelegate.swift index f73c543f55f58dd42442717890414bf9ee649a16..e5ebafdcd70635d29cb49827b6f9e64d4424ece7 100644 --- a/Pendu/AppDelegate.swift +++ b/Pendu/AppDelegate.swift @@ -13,10 +13,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate { - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { - // Override point for customization after application launch. - return true - } + func application(_ application: UIApplication, didFinishLaunchingWithOptions + launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. + return true + } // MARK: UISceneSession Lifecycle diff --git a/Pendu/Base.lproj/Main.storyboard b/Pendu/Base.lproj/Main.storyboard new file mode 100644 index 0000000000000000000000000000000000000000..8edcd760af13dbc69a1ca6aa116c5d3368c5b766 --- /dev/null +++ b/Pendu/Base.lproj/Main.storyboard @@ -0,0 +1,99 @@ +<?xml version="1.0" encoding="UTF-8"?> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r"> + <device id="retina6_1" orientation="portrait" appearance="light"/> + <dependencies> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/> + <capability name="Safe area layout guides" minToolsVersion="9.0"/> + <capability name="System colors in document resources" minToolsVersion="11.0"/> + <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> + </dependencies> + <scenes> + <!--View Controller--> + <scene sceneID="tne-QT-ifu"> + <objects> + <viewController id="BYZ-38-t0r" customClass="ViewController" customModule="Pendu" customModuleProvider="target" sceneMemberID="viewController"> + <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC"> + <rect key="frame" x="0.0" y="0.0" width="414" height="896"/> + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> + <subviews> + <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="hqdefault.jpeg" translatesAutoresizingMaskIntoConstraints="NO" id="pv2-ee-Khp"> + <rect key="frame" x="0.0" y="-43" width="414" height="319"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> + </imageView> + <textField opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="iRK-mL-RC3"> + <rect key="frame" x="106" y="400" width="184" height="34"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> + <fontDescription key="fontDescription" type="system" pointSize="14"/> + <textInputTraits key="textInputTraits"/> + </textField> + <pickerView contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="LNU-nY-Uyk"> + <rect key="frame" x="0.0" y="565" width="414" height="162"/> + <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/> + </pickerView> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Choisissez un theme" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dAa-qb-1JB"> + <rect key="frame" x="119" y="484" width="158" height="21"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> + <fontDescription key="fontDescription" type="system" pointSize="17"/> + <nil key="textColor"/> + <nil key="highlightedColor"/> + </label> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="choissisez votre pseudo" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="doS-CU-ueI"> + <rect key="frame" x="106" y="351" width="184" height="21"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> + <fontDescription key="fontDescription" type="system" pointSize="17"/> + <nil key="textColor"/> + <nil key="highlightedColor"/> + </label> + <button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Rxj-5T-1Nw"> + <rect key="frame" x="117" y="720" width="181" height="54"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> + <state key="normal" title="Button"/> + <buttonConfiguration key="configuration" style="filled" title="Lancer Partie"/> + <connections> + <action selector="LancerPartie:" destination="BYZ-38-t0r" eventType="touchUpInside" id="ccG-OM-Emx"/> + </connections> + </button> + <segmentedControl opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="NvB-ZN-BTJ"> + <rect key="frame" x="144" y="526" width="109" height="32"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> + <segments> + <segment title="Facile"/> + <segment title="Hard"/> + </segments> + </segmentedControl> + <button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="lae-hh-psQ"> + <rect key="frame" x="119" y="284" width="160" height="31"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> + <state key="normal" title="Button"/> + <buttonConfiguration key="configuration" style="gray"> + <attributedString key="attributedTitle"> + <fragment content="Classement"/> + </attributedString> + </buttonConfiguration> + <connections> + <action selector="AfficherClassement:" destination="BYZ-38-t0r" eventType="touchUpInside" id="up5-UE-mBH"/> + </connections> + </button> + </subviews> + <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/> + <color key="backgroundColor" systemColor="systemBackgroundColor"/> + </view> + <connections> + <outlet property="choixNiv" destination="NvB-ZN-BTJ" id="fAA-St-woR"/> + <outlet property="choixTheme" destination="LNU-nY-Uyk" id="Fff-Y6-Z8A"/> + <outlet property="classement" destination="lae-hh-psQ" id="YEG-ma-abh"/> + <outlet property="pseudoinput" destination="iRK-mL-RC3" id="v77-OK-9QK"/> + </connections> + </viewController> + <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/> + </objects> + <point key="canvasLocation" x="131.8840579710145" y="81.696428571428569"/> + </scene> + </scenes> + <resources> + <image name="hqdefault.jpeg" width="480" height="360"/> + <systemColor name="systemBackgroundColor"> + <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> + </systemColor> + </resources> +</document> diff --git a/Pendu/GameEngine.swift b/Pendu/GameEngine.swift new file mode 100644 index 0000000000000000000000000000000000000000..e99a54aed2060e237cf16568522c31fb489b48a7 --- /dev/null +++ b/Pendu/GameEngine.swift @@ -0,0 +1,183 @@ +// +// GameEngine.swift +// Pendu +// +// Created by Sofiane Lasri-Trienpont on 09/05/2023. +// + +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 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 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() { + // + } + + 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) + word = listThemeAnimalsEasy[randomInt] + } else { + let randomInt = Int.random(in: 0..<listThemeAnimalsHard.count) + word = listThemeAnimalsHard[randomInt] + } + } else if theme == "Sports"{ + if difficulty == "Easy"{ + let randomInt = Int.random(in: 0..<listThemeSportsEasy.count) + word = listThemeAnimalsEasy[randomInt] + } else { + let randomInt = Int.random(in: 0..<listThemeSportsHard.count) + word = listThemeSportsHard[randomInt] + } + } else if theme == "Food"{ + if difficulty == "Easy"{ + let randomInt = Int.random(in: 0..<listThemeFoodEasy.count) + word = listThemeFoodEasy[randomInt] + } else { + let randomInt = Int.random(in: 0..<listThemeFoodHard.count) + word = listThemeFoodHard[randomInt] + } + } else if theme == "Cities"{ + if difficulty == "Easy"{ + let randomInt = Int.random(in: 0..<listThemeCitiesEasy.count) + word = listThemeCitiesEasy[randomInt] + } else { + let randomInt = Int.random(in: 0..<listThemeCitiesHard.count) + word = listThemeCitiesHard[randomInt] + } + } else if theme == "Colors"{ + if difficulty == "Easy"{ + let randomInt = Int.random(in: 0..<listThemeColorsEasy.count) + word = listThemeColorsEasy[randomInt] + } else { + let randomInt = Int.random(in: 0..<listThemeColorsHard.count) + word = listThemeColorsHard[randomInt] + } + } + return word + } + + public func guessLetter(letter: Character) -> Bool { + if(isGameOver()){ + return false; + } + + guessedLetters.append(letter); + + if wordToGuess.contains(letter) { + 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 { + if(remainingLives > 0) { + return false; + } + return true; + } + + 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 { + // Récupération du classement depuis le serveur + } +} 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 new file mode 100644 index 0000000000000000000000000000000000000000..2d686e6810f5920f9081450855e4ccf41f957ea9 --- /dev/null +++ b/Pendu/GameEngineTests.swift @@ -0,0 +1,32 @@ +// +// GameEngineTests.swift +// PenduTests +// +// Created by Sofiane Lasri-Trienpont on 09/05/2023. +// + +import XCTest + +class GameEngineTests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testIsGameOver() throws { + let game:GameEngine = GameEngine(); + XCTAssertEqual(false, game.isGameOver()); + } + + func testStartNewGame() throws { + let game:GameEngine = GameEngine(); + let mot1 = game.WordToGuess(theme: "Sports", difficulty: "Hard") + 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 50d2514e87d2e6274170ca7165bbfd11f32c64e3..b13b2ba73d77d3a2042ecea1671b4756a3529846 100644 --- a/Pendu/Pendu.xcdatamodeld/Pendu.xcdatamodel/contents +++ b/Pendu/Pendu.xcdatamodeld/Pendu.xcdatamodel/contents @@ -1,4 +1,12 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> -<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="1" systemVersion="11A491" minimumToolsVersion="Automatic" sourceLanguage="Swift" usedWithCloudKit="false" userDefinedModelVersionIdentifier=""> - <elements/> +<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="20086" systemVersion="21E258" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier=""> + <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="Score" positionX="-63" positionY="-18" width="128" height="89"/> + </elements> </model> \ No newline at end of file diff --git a/Pendu/ViewController.swift b/Pendu/ViewController.swift new file mode 100644 index 0000000000000000000000000000000000000000..96f8673eb4941f734bc7d287ce59e01a9a073813 --- /dev/null +++ b/Pendu/ViewController.swift @@ -0,0 +1,62 @@ +import UIKit + +class ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate { + + @IBOutlet weak var classement: UIButton! + @IBOutlet weak var pseudoinput: UITextField! + @IBOutlet weak var choixTheme: UIPickerView! + @IBOutlet weak var choixNiv: UISegmentedControl! + + let pickerData = ["Animals", "Sports", "Food", "Cities", "Colors"] + let gameEngine : GameEngine = GameEngine() + override func viewDidLoad() { + super.viewDidLoad() + choixTheme.dataSource = self + choixTheme.delegate = self + } + + + + @IBAction func LancerPartie(_ sender: Any) { + guard let pseudo = pseudoinput.text else { + return + } + + let niveauIndex = choixNiv.selectedSegmentIndex + let niveau = choixNiv.titleForSegment(at: niveauIndex) + + let themeIndex = choixTheme.selectedRow(inComponent: 0) + let theme = pickerData[themeIndex] + + // Utilisez les valeurs récupérées comme vous le souhaitez + print("Pseudo: \(pseudo)") + print("Niveau: \(niveau ?? "")") + print("Thème: \(theme)") + + // Ajoutez votre code supplémentaire ici + let difficulty = niveau ?? "" + + let word = gameEngine.WordToGuess(theme: theme, difficulty: difficulty) + print("Mot à deviner: \(word)") + } + + // MARK: - UIPickerViewDataSource + + func numberOfComponents(in pickerView: UIPickerView) -> Int { + return 1 + } + + func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { + return pickerData.count + } + + // MARK: - UIPickerViewDelegate + + func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { + return pickerData[row] + } + + func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { + // Code à exécuter lorsque l'utilisateur sélectionne une valeur dans le pickerView. + } +} diff --git a/PenduTests/PenduTests.swift b/PenduTests/PenduTests.swift index d659345db8cafa5fdd6de0292abc93547ad1b6e9..b960a7496e65129377ed43b4c8533080a84deec9 100644 --- a/PenduTests/PenduTests.swift +++ b/PenduTests/PenduTests.swift @@ -32,5 +32,5 @@ class PenduTests: XCTestCase { // Put the code you want to measure the time of here. } } - + }