Ios game where the uses has a set amount of time to flip over cards and match them .
Swift
swiftui-Card-Matching-Game
App using Swift 5, to create a card memory game. The user can only have two cards filped over at the same time. When a
card is flipped over a timer starts forcing the player to match the cards quickly. Once a card is matched the card disapperars. After, the
game is over the user can press a restart button to play again.
This mobile app was created following the MVVM framework. The Model is responsible for creating the cards, and controlling the logic
involved in matching the cards.
📷 Screenshots
💻 Code Examples
MemoryGame.swift extract: checks if the cards that the user selected are matching and if they are, the cards are removed from the screen.
Additionally, the file also controls the time limit that the user has.
import Foundation
structMemoryGame<CardContent>where CardContent:Equatable{private(set)varcards:Array<Card>privatevarindexOfTheOneAndOnlyFaceUpCard:Int?{get{
cards.indices.filter{cards[$0].isFaceUp}.only}set{
for index in cards.indices{cards[index].isFaceUp = index == newValue
}}}mutatingfunc choose(card:Card){
if let chosenIndex = cards.firstIndex(matching: card), !cards[chosenIndex].isFaceUp,!cards[chosenIndex].isMatched{
if let potentialMatchIndex = indexOfTheOneAndOnlyFaceUpCard{
if cards[chosenIndex].Content ==cards[potentialMatchIndex].Content{cards[chosenIndex].isMatched = true
cards[potentialMatchIndex].isMatched = true
}self.cards[chosenIndex].isFaceUp = !self.cards[chosenIndex].isFaceUp
}else{
indexOfTheOneAndOnlyFaceUpCard = chosenIndex
}}}init(pairs:Int, cardContentFactory:(Int)->CardContent){
cards =Array<Card>()
for pairIndex in 0..<pairs {letcontent=cardContentFactory(pairIndex)
cards.append(Card(Content: content, id: pairIndex*2))
cards.append(Card(Content: content, id: pairIndex*2+1))}
cards.shuffle()}structCard:Identifiable{varisFaceUp:Bool= false{
didSet{
if isFaceUp{startUsingBonusTime()}else{stopUsingBonusTime()}}}varisMatched:Bool= false{
didSet {stopUsingBonusTime()}}varContent:CardContentvarid:IntvarbonusTimeLimit:TimeInterval=6privatevarfaceUpTime:TimeInterval{
if let lastFaceUpDate =self.lastFaceUpDate {return pastFaceUpTime + Date().timeIntervalSince(lastFaceUpDate)}else{return pastFaceUpTime
}}varlastFaceUpDate:Date?varpastFaceUpTime:TimeInterval=0varbonusTimeRemaining:TimeInterval{max(0, bonusTimeLimit-faceUpTime)}varbonusRemaining:Double{(bonusTimeLimit >0 && bonusTimeRemaining >0) ? bonusTimeRemaining/bonusTimeLimit :0}varhasEarnedBonus:Bool{
isMatched && bonusTimeRemaining >0}varisComsumingBonusTime:Bool{
isFaceUp && !isMatched && bonusTimeRemaining >0}privatemutatingfunc startUsingBonusTime(){
if isComsumingBonusTime, lastFaceUpDate ==nil{
lastFaceUpDate =Date()}}privatemutatingfunc stopUsingBonusTime(){
pastFaceUpTime = faceUpTime
self.lastFaceUpDate =nil}}}
📁 License
This project is licensed under the terms of the MIT license.