рд╕реНрд╡рд┐рдлреНрдЯ рдореЗрдВ рдореЗрдореЛрд░реА рдХрд╛рд░реНрдб рдЧреЗрдо рд▓рд┐рдЦрдирд╛

рд╕реНрд╡рд┐рдлреНрдЯ рдореЗрдВ рдореЗрдореЛрд░реА рдХрд╛рд░реНрдб рдЧреЗрдо рд▓рд┐рдЦрдирд╛

рдпрд╣ рдЖрд▓реЗрдЦ рдПрдХ рд╕рд░рд▓ рдореЗрдореЛрд░реА рдкреНрд░рд╢рд┐рдХреНрд╖рдг рдЧреЗрдо рдмрдирд╛рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдореБрдЭреЗ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдкрд╕рдВрдж рд╣реИред рдЕрдкрдиреЗ рдЖрдк рдореЗрдВ рдЕрдЪреНрдЫрд╛ рд╣реЛрдиреЗ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЖрдк рдЖрдЧреЗ рдмрдврд╝рддреЗ рд╣реБрдП рд╕реНрд╡рд┐рдлреНрдЯ рдХрдХреНрд╖рд╛рдУрдВ рдФрд░ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдереЛрдбрд╝рд╛ рдФрд░ рд╕реАрдЦреЗрдВрдЧреЗред рд▓реЗрдХрд┐рди рд╢реБрд░реВ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдЖрдЗрдП рдЦреЗрд▓ рдХреЛ рд╕рдордЭреЗрдВред

рдЕрдиреБрд╕реНрдорд╛рд░рдХ: "рд╣реИрдмрд░" рдХреЗ рд╕рднреА рдкрд╛рдардХреЛрдВ рдХреЗ рд▓рд┐рдП - "рд╣реИрдмрд░" рдкреНрд░рдЪрд╛рд░ рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХрд┐рд╕реА рднреА рд╕реНрдХрд┐рд▓рдмреЙрдХреНрд╕ рдкрд╛рдареНрдпрдХреНрд░рдо рдореЗрдВ рдирд╛рдорд╛рдВрдХрди рдХрд░рддреЗ рд╕рдордп 10 рд░реВрдмрд▓ рдХреА рдЫреВрдЯред

рд╕реНрдХрд┐рд▓рдмреЙрдХреНрд╕ рдЕрдиреБрд╢рдВрд╕рд╛ рдХрд░рддрд╛ рд╣реИ: рд╢реИрдХреНрд╖рд┐рдХ рдСрдирд▓рд╛рдЗрди рдкрд╛рдареНрдпрдХреНрд░рдо "рдкреЗрд╢рд╛ рдЬрд╛рд╡рд╛ рдбреЗрд╡рд▓рдкрд░".

рдореЗрдореЛрд░реА рдХрд╛рд░реНрдб рдХреИрд╕реЗ рдЦреЗрд▓реЗрдВ

рдЦреЗрд▓ рддрд╛рд╢ рдХреЗ рдкрддреНрддреЛрдВ рдХреЗ рдПрдХ рд╕реЗрдЯ рдХреЗ рдкреНрд░рджрд░реНрд╢рди рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИред рд╡реЗ рдиреАрдЪреЗ рдХреА рдУрд░ рдореБрдВрд╣ рдХрд░рдХреЗ рд▓реЗрдЯрддреЗ рд╣реИрдВ (рдХреНрд░рдорд╢рдГ, рдЫрд╡рд┐ рдиреАрдЪреЗ рдХреА рдУрд░)ред рдЬрдм рдЖрдк рдХрд┐рд╕реА рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рддреЗ рд╣реИрдВ рддреЛ рдЫрд╡рд┐ рдХреБрдЫ рд╕реЗрдХрдВрдб рдХреЗ рд▓рд┐рдП рдЦреБрд▓ рдЬрд╛рддреА рд╣реИред

рдЦрд┐рд▓рд╛рдбрд╝реА рдХрд╛ рдХрд╛рд░реНрдп рд╕рдорд╛рди рдЪрд┐рддреНрд░реЛрдВ рд╡рд╛рд▓реЗ рд╕рднреА рдХрд╛рд░реНрдб рдвреВрдВрдврдирд╛ рд╣реИред рдпрджрд┐, рдкрд╣рд▓рд╛ рдХрд╛рд░реНрдб рдЦреЛрд▓рдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдк рджреВрд╕рд░рд╛ рдХрд╛рд░реНрдб рдкрд▓рдЯрддреЗ рд╣реИрдВ рдФрд░ рдЪрд┐рддреНрд░ рдореЗрд▓ рдЦрд╛рддреЗ рд╣реИрдВ, рддреЛ рджреЛрдиреЛрдВ рдХрд╛рд░реНрдб рдЦреБрд▓реЗ рд░рд╣рддреЗ рд╣реИрдВред рдпрджрд┐ рд╡реЗ рдореЗрд▓ рдирд╣реАрдВ рдЦрд╛рддреЗ рд╣реИрдВ, рддреЛ рдХрд╛рд░реНрдб рдлрд┐рд░ рд╕реЗ рдмрдВрдж рдХрд░ рджрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред рд▓рдХреНрд╖реНрдп рд╕рдм рдХреБрдЫ рдЦреЛрд▓рдирд╛ рд╣реИ.

рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╕рдВрд░рдЪрдирд╛

рдЗрд╕ рдЧреЗрдо рдХрд╛ рд╕рд░рд▓ рд╕рдВрд╕реНрдХрд░рдг рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдкрдХреЛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдШрдЯрдХреЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА:

  • рдПрдХ рдирд┐рдпрдВрддреНрд░рдХ: GameController.swiftред
  • рдПрдХ рджреГрд╢реНрдп: рдХрд╛рд░реНрдбрд╕реЗрд▓.рд╕реНрд╡рд┐рдлреНрдЯред
  • рджреЛ рдореЙрдбрд▓: рдореЗрдореЛрд░реАрдЧреЗрдо.рд╕реНрд╡рд┐рдлреНрдЯ рдФрд░ рдХрд╛рд░реНрдб.рд╕реНрд╡рд┐рдлреНрдЯред
  • Main.storyboard рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рдШрдЯрдХреЛрдВ рдХрд╛ рдкреВрд░рд╛ рд╕реЗрдЯ рдЙрдкрд▓рдмреНрдз рд╣реИред

рд╣рдо рдЦреЗрд▓ рдХреЗ рд╕рдмрд╕реЗ рд╕рд░рд▓ рдШрдЯрдХ, рдХрд╛рд░реНрдб рд╕реЗ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВред

рдХрд╛рд░реНрдб.рд╕реНрд╡рд┐рдлреНрдЯ

рдХрд╛рд░реНрдб рдореЙрдбрд▓ рдореЗрдВ рддреАрди рдЧреБрдг рд╣реЛрдВрдЧреЗ: рдкреНрд░рддреНрдпреЗрдХ рдХреЛ рдкрд╣рдЪрд╛рдирдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдИрдбреА, рдХрд╛рд░реНрдб рдХреА рд╕реНрдерд┐рддрд┐ (рдЫрд┐рдкреА рдпрд╛ рдЦреБрд▓реА) рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рджрд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛ рдПрдХ рдмреВрд▓рд┐рдпрди рд╡реИрд░рд┐рдПрдмрд▓, рдФрд░ рдХрд╛рд░реНрдб рдкрд░ рдЫрд╡рд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рдЖрд░реНрдЯрд╡рд░реНрдХрдпреВрдЖрд░рдПрд▓ред

class Card {        
    var id: String    
    var shown: Bool = false    
    var artworkURL: UIImage!
}

рдорд╛рдирдЪрд┐рддреНрд░реЛрдВ рдХреЗ рд╕рд╛рде рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕рд╣рднрд╛рдЧрд┐рддрд╛ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдкрдХреЛ рдЗрди рд╡рд┐рдзрд┐рдпреЛрдВ рдХреА рднреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА:

рдХрд╛рд░реНрдб рдкрд░ рдЫрд╡рд┐ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреА рд╡рд┐рдзрд┐. рдпрд╣рд╛рдВ рд╣рдо рд╕рднреА рд╕рдВрдкрддреНрддрд┐рдпреЛрдВ рдХреЛ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдкрд░ рд░реАрд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВред рдЖрдИрдбреА рдХреЗ рд▓рд┐рдП, рд╣рдо NSUUIS().uuidString рдХреЛ рдХреЙрд▓ рдХрд░рдХреЗ рдПрдХ рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рдЖрдИрдбреА рдЙрддреНрдкрдиреНрди рдХрд░рддреЗ рд╣реИрдВред

init(image: UIImage) {        
    self.id = NSUUID().uuidString        
    self.shown = false        
    self.artworkURL = image    
}

рдЖрдИрдбреА рдХрд╛рд░реНрдб рдХреА рддреБрд▓рдирд╛ рдХрд░рдиреЗ рдХреА рд╡рд┐рдзрд┐.

func equals(_ card: Card) -> Bool {
    return (card.id == id)    
}

рдкреНрд░рддреНрдпреЗрдХ рдХрд╛рд░реНрдб рдХреА рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдмрдирд╛рдиреЗ рдХреА рд╡рд┐рдзрд┐ - рдмрдбрд╝реА рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рд╕рдорд╛рди рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред рдпрд╣ рд╡рд┐рдзрд┐ рд╕рдорд╛рди рдорд╛рдиреЛрдВ рд╡рд╛рд▓рд╛ рдХрд╛рд░реНрдб рд▓реМрдЯрд╛ рджреЗрдЧреА.

func copy() -> Card {        
    return Card(card: self)    
}
 
init(card: Card) {        
    self.id = card.id        
    self.shown = card.shown        
    self.artworkURL = card.artworkURL    
}

рдФрд░ рд╢реБрд░реБрдЖрдд рдореЗрдВ рдХрд╛рд░реНрдбреЛрдВ рдХреЛ рдлреЗрд░рдмрджрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдФрд░ рд╡рд┐рдзрд┐ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рд╣рдо рдЗрд╕реЗ рдРрд░реЗ рдХреНрд▓рд╛рд╕ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдмрдирд╛ рджреЗрдВрдЧреЗред

extension Array {    
    mutating func shuffle() {        
        for _ in 0...self.count {            
            sort { (_,_) in arc4random() < arc4random() }        
        }   
    }
}

рдФрд░ рдпрд╣рд╛рдВ рд╕рднреА рдЧреБрдгреЛрдВ рдФрд░ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рд░реНрдб рдореЙрдбрд▓ рдХреЗ рд▓рд┐рдП рдХреЛрдб рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реИред

class Card {
    
    var id: String
    var shown: Bool = false
    var artworkURL: UIImage!
    
    static var allCards = [Card]()
 
    init(card: Card) {
        self.id = card.id
        self.shown = card.shown
        self.artworkURL = card.artworkURL
    }
    
    init(image: UIImage) {
        self.id = NSUUID().uuidString
        self.shown = false
        self.artworkURL = image
    }
    
    func equals(_ card: Card) -> Bool {
        return (card.id == id)
    }
    
    func copy() -> Card {
        return Card(card: self)
    }
}
 
extension Array {
    mutating func shuffle() {
        for _ in 0...self.count {
            sort { (_,_) in arc4random() < arc4random() }
        }
    }
}

рдЖрдЧреЗ рдмрдврд╝реЗрдВред

рджреВрд╕рд░рд╛ рдореЙрдбрд▓ рдореЗрдореЛрд░реАрдЧреЗрдо рд╣реИ, рдпрд╣рд╛рдВ рд╣рдордиреЗ 4*4 рдЧреНрд░рд┐рдб рд╕реЗрдЯ рдХрд┐рдпрд╛ рд╣реИред рдореЙрдбрд▓ рдореЗрдВ рдХрд╛рд░реНрдб (рдЧреНрд░рд┐рдб рдкрд░ рдХрд╛рд░реНрдбреЛрдВ рдХреА рдПрдХ рд╕рд░рдгреА), рдкрд╣рд▓реЗ рд╕реЗ рдЦреБрд▓реЗ рдХрд╛рд░реНрдбреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рдХрд╛рд░реНрдб рд╢реЛ рдХреА рдЧрдИ рд╕рд░рдгреА рдФрд░ рдЧреЗрдо рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рдЯреНрд░реИрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдмреВрд▓рд┐рдпрди рд╡реЗрд░рд┐рдПрдмрд▓ рдкреНрд▓реЗрдЗрдВрдЧ рдЬреИрд╕реЗ рдЧреБрдг рд╣реЛрдВрдЧреЗред

class MemoryGame {        
    var cards:[Card] = [Card]()    
    var cardsShown:[Card] = [Card]()    
    var isPlaying: Bool = false
}

рд╣рдореЗрдВ рдЧреНрд░рд┐рдб рдХреЗ рд╕рд╛рде рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рдЗрдВрдЯрд░реИрдХреНрд╢рди рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рддрд░реАрдХреЗ рднреА рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред

рдПрдХ рд╡рд┐рдзрд┐ рдЬреЛ рдЧреНрд░рд┐рдб рдореЗрдВ рдХрд╛рд░реНрдбреЛрдВ рдХреЛ рдлреЗрдВрдЯрддреА рд╣реИред

func shuffleCards(cards:[Card]) -> [Card] {       
    var randomCards = cards        
    randomCards.shuffle()                
 
    return randomCards    
}

рдирдпрд╛ рдЧреЗрдо рдмрдирд╛рдиреЗ рдХреА рд╡рд┐рдзрд┐. рдпрд╣рд╛рдВ рд╣рдо рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд▓реЗрдЖрдЙрдЯ рд╢реБрд░реВ рдХрд░рдиреЗ рдФрд░ isPlaying рд╡реИрд░рд┐рдПрдмрд▓ рдХреЛ рд╕рддреНрдп рдкрд░ рдЖрд░рдВрдн рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд╣рд▓реА рд╡рд┐рдзрд┐ рдХрд╣рддреЗ рд╣реИрдВред

func newGame(cardsArray:[Card]) -> [Card] {       
    cards = shuffleCards(cards: cardsArray)        
    isPlaying = true            
 
    return cards    
}

рдЕрдЧрд░ рд╣рдо рдЦреЗрд▓ рдХреЛ рдкреБрдирдГ рдЖрд░рдВрдн рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рдлрд┐рд░ рд╣рдо isPlaying рд╡реИрд░рд┐рдПрдмрд▓ рдХреЛ рдЧрд▓рдд рдкрд░ рд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдХрд╛рд░реНрдб рдХреЗ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд▓реЗрдЖрдЙрдЯ рдХреЛ рд╣рдЯрд╛ рджреЗрддреЗ рд╣реИрдВред

func restartGame() {        
    isPlaying = false                
    cards.removeAll()        
    cardsShown.removeAll()    
}

рдХреНрд▓рд┐рдХ рдХрд┐рдП рдЧрдП рдХрд╛рд░реНрдбреЛрдВ рдХреЛ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреА рд╡рд┐рдзрд┐. рдЙрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдж рдореЗрдВ рдФрд░ рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реАред

func cardAtIndex(_ index: Int) -> Card? {        
    if cards.count > index {            
        return cards[index]        
    } else {            
        return nil        
    }    
}

рдПрдХ рд╡рд┐рдзрд┐ рдЬреЛ рдХрд┐рд╕реА рд╡рд┐рд╢рд┐рд╖реНрдЯ рдХрд╛рд░реНрдб рдХреА рд╕реНрдерд┐рддрд┐ рд▓реМрдЯрд╛рддреА рд╣реИред

func indexForCard(_ card: Card) -> Int? {        
    for index in 0...cards.count-1 {            
        if card === cards[index] {                
            return index            
        }      
    }
        
    return nil    
}

рдорд╛рдирдХ рдХреЗ рд╕рд╛рде рдЪрдпрдирд┐рдд рдХрд╛рд░реНрдб рдХреЗ рдЕрдиреБрдкрд╛рд▓рди рдХреА рдЬрд╛рдБрдЪ рдХрд░рдирд╛ред

func unmatchedCardShown() -> Bool {
    return cardsShown.count % 2 != 0
}

рдпрд╣ рд╡рд┐рдзрд┐ **cardsShowed** рд╕рд░рдгреА рдореЗрдВ рдЕрдВрддрд┐рдо рддрддреНрд╡ рдХреЛ рдкрдврд╝рддреА рд╣реИ рдФрд░ рдЧреИрд░-рдорд┐рд▓рд╛рди рд╡рд╛рд▓реЗ рдХрд╛рд░реНрдб рдХреЛ рд╡рд╛рдкрд╕ рдХрд░ рджреЗрддреА рд╣реИред

func didSelectCard(_ card: Card?) {        
    guard let card = card else { return }                
    
    if unmatchedCardShown() {            
        let unmatched = unmatchedCard()!                        
        
        if card.equals(unmatched) {          
            cardsShown.append(card)            
        } else {                
            let secondCard = cardsShown.removeLast()      
        }                    
    } else {            
        cardsShown.append(card)        
    }                
    
    if cardsShown.count == cards.count {            
        endGame()        
    }    
}

Main.storyboard рдФрд░ GameController.swift

Main.storyboard рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:

рд╕реНрд╡рд┐рдлреНрдЯ рдореЗрдВ рдореЗрдореЛрд░реА рдХрд╛рд░реНрдб рдЧреЗрдо рд▓рд┐рдЦрдирд╛

рдкреНрд░рд╛рд░рдВрдн рдореЗрдВ, рдЖрдкрдХреЛ рдЧреНрд░рд┐рдб рдХреЗ рд▓рд┐рдП рдЫрд╡рд┐рдпреЛрдВ рд╕рд╣рд┐рдд, рдирд┐рдпрдВрддреНрд░рдХ рдореЗрдВ рдирдП рдЧреЗрдо рдХреЛ viewDidLoad рдХреЗ рд░реВрдк рдореЗрдВ рд╕реЗрдЯ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдЧреЗрдо рдореЗрдВ, рдпрд╣ рд╕рдм 4*4 рдХрд▓реЗрдХреНрд╢рди рд╡реНрдпреВ рджреНрд╡рд╛рд░рд╛ рджрд░реНрд╢рд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдпрджрд┐ рдЖрдк рдЕрднреА рддрдХ рдХрд▓реЗрдХреНрд╢рди рд╡реНрдпреВ рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рдирд╣реАрдВ рд╣реИрдВ, рддреЛ рдпрд╣ рдпрд╣рд╛рдВ рд╣реИ рдЖрдк рдЕрдкрдиреА рдЖрд╡рд╢реНрдпрдХ рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ.

рд╣рдо рдЧреЗрдордХрдВрдЯреНрд░реЛрд▓рд░ рдХреЛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рд░реВрдЯ рдХрдВрдЯреНрд░реЛрд▓рд░ рдХреЗ рд░реВрдк рдореЗрдВ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░реЗрдВрдЧреЗред рдЧреЗрдордХрдВрдЯреНрд░реЛрд▓рд░ рдореЗрдВ рдПрдХ рд╕рдВрдЧреНрд░рд╣ рджреГрд╢реНрдп рд╣реЛрдЧрд╛ рдЬрд┐рд╕реЗ рд╣рдо IBOutlet рдХреЗ рд░реВрдк рдореЗрдВ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░реЗрдВрдЧреЗред рдПрдХ рдЕрдиреНрдп рд╕рдВрджрд░реНрдн IBAction onStartGame() рдмрдЯрди рдХрд╛ рд╣реИ, рдпрд╣ рдПрдХ UIButton рд╣реИ, рдЖрдк рдЗрд╕реЗ PLAY рдирд╛рдордХ рд╕реНрдЯреЛрд░реАрдмреЛрд░реНрдб рдореЗрдВ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВред

рдирд┐рдпрдВрддреНрд░рдХреЛрдВ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдереЛрдбрд╝рд╛:

  • рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рджреЛ рдореБрдЦреНрдп рдСрдмреНрдЬреЗрдХреНрдЯ рдкреНрд░рд╛рд░рдВрдн рдХрд░рддреЗ рд╣реИрдВ - рдЧреНрд░рд┐рдб: рдЧреЗрдо = рдореЗрдореЛрд░реАрдЧреЗрдо(), рдФрд░ рдХрд╛рд░реНрдб рдХрд╛ рдПрдХ рд╕реЗрдЯ: рдХрд╛рд░реНрдб = [рдХрд╛рд░реНрдб]()ред
  • рд╣рдордиреЗ рд╢реБрд░реБрдЖрддреА рд╡реЗрд░рд┐рдПрдмрд▓реНрд╕ рдХреЛ viewDidLoad рдХреЗ рд░реВрдк рдореЗрдВ рд╕реЗрдЯ рдХрд┐рдпрд╛ рд╣реИ, рдпрд╣ рдкрд╣рд▓реА рд╡рд┐рдзрд┐ рд╣реИ рдЬрд┐рд╕реЗ рдЧреЗрдо рдЪрд▓рдиреЗ рдХреЗ рджреМрд░рд╛рди рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред
  • рд╕рдВрдЧреНрд░рд╣ рджреГрд╢реНрдп рдХреЛ рдЫрд┐рдкрд╛ рд╣реБрдЖ рдкрд░ рд╕реЗрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдЬрдм рддрдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ PLAY рдирд╣реАрдВ рджрдмрд╛рддрд╛ рддрдм рддрдХ рд╕рднреА рдХрд╛рд░реНрдб рдЫрд┐рдкреЗ рд░рд╣рддреЗ рд╣реИрдВред
  • рдЬреИрд╕реЗ рд╣реА рд╣рдо PLAY рджрдмрд╛рддреЗ рд╣реИрдВ, onStartGame IBAction рдЕрдиреБрднрд╛рдЧ рд╢реБрд░реВ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рд╣рдо CollectionView isHidden рдкреНрд░реЙрдкрд░реНрдЯреА рдХреЛ рдЧрд▓рдд рдкрд░ рд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВ рддрд╛рдХрд┐ рдХрд╛рд░реНрдб рджрд┐рдЦрд╛рдИ рджреЗ рд╕рдХреЗрдВред
  • рд╣рд░ рдмрд╛рд░ рдЬрдм рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛрдИ рдХрд╛рд░реНрдб рдЪреБрдирддрд╛ рд╣реИ, рддреЛ madeSelectItemAt рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╡рд┐рдзрд┐ рдореЗрдВ рд╣рдо рдореБрдЦреНрдп рдЧреЗрдо рд▓реЙрдЬрд┐рдХ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП digSelectCard рдХрд╣рддреЗ рд╣реИрдВред

рдпрд╣рд╛рдВ рдЕрдВрддрд┐рдо рдЧреЗрдордХрдВрдЯреНрд░реЛрд▓рд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реИ:

class GameController: UIViewController {
 
    @IBOutlet weak var collectionView: UICollectionView!
    
    let game = MemoryGame()
    var cards = [Card]()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        game.delegate = self
        
        collectionView.dataSource = self
        collectionView.delegate = self
        collectionView.isHidden = true
        
        APIClient.shared.getCardImages { (cardsArray, error) in
            if let _ = error {
                // show alert
            }
            
            self.cards = cardsArray!
            self.setupNewGame()
        }
    }
    
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        
        if game.isPlaying {
            resetGame()
        }
    }
    
    func setupNewGame() {
        cards = game.newGame(cardsArray: self.cards)
        collectionView.reloadData()
    }
    
    func resetGame() {
        game.restartGame()
        setupNewGame()
    }
    
    @IBAction func onStartGame(_ sender: Any) {
        collectionView.isHidden = false
    }
}
 
// MARK: - CollectionView Delegate Methods
extension GameController: UICollectionViewDelegate, UICollectionViewDataSource {
    
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return cards.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CardCell", for: indexPath) as! CardCell
        cell.showCard(false, animted: false)
        
        guard let card = game.cardAtIndex(indexPath.item) else { return cell }
        cell.card = card
        
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        let cell = collectionView.cellForItem(at: indexPath) as! CardCell
        
        if cell.shown { return }
        game.didSelectCard(cell.card)
        
        collectionView.deselectItem(at: indexPath, animated:true)
    }
}

рдЕрдм рдХреБрдЫ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░рддреЗ рд╣реИрдВред

рдкреНрд░реЛрдЯреЛрдХреЙрд▓

рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рд╕реНрд╡рд┐рдлреНрдЯ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдХрд╛ рдореВрд▓ рд╣реИред рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХрд┐рд╕реА рд╡рд░реНрдЧ, рд╕рдВрд░рдЪрдирд╛ рдпрд╛ рдЧрдгрдирд╛ рдХреЗ рд▓рд┐рдП рдирд┐рдпрдореЛрдВ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдкреНрд░рджрд╛рди рдХрд░рддреЗ рд╣реИрдВред рдпрд╣ рд╕рд┐рджреНрдзрд╛рдВрдд рдЖрдкрдХреЛ рдореЙрдбреНрдпреВрд▓рд░ рдФрд░ рдПрдХреНрд╕реНрдЯреЗрдВрд╕рд┐рдмрд▓ рдХреЛрдб рд▓рд┐рдЦрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдпрд╣ рдПрдХ рдкреИрдЯрд░реНрди рд╣реИ рдЬрд┐рд╕реЗ рд╣рдо рдЧреЗрдордХрдВрдЯреНрд░реЛрд▓рд░ рдореЗрдВ рдХрд▓реЗрдХреНрд╢рди рд╡реНрдпреВ рдХреЗ рд▓рд┐рдП рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд▓рд╛рдЧреВ рдХрд░ рд░рд╣реЗ рд╣реИрдВред рдЕрдм рдЖрдЗрдП рдЕрдкрдирд╛ рд╕реНрд╡рдпрдВ рдХрд╛ рд╕рдВрд╕реНрдХрд░рдг рдмрдирд╛рдПрдВред рд╕рд┐рдВрдЯреИрдХреНрд╕ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦреЗрдЧрд╛:

protocol MemoryGameProtocol {
    //protocol definition goes here
}

рд╣рдо рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдПрдХ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рд╣рдореЗрдВ рдХрд┐рд╕реА рд╡рд░реНрдЧ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдирд┐рдпрдореЛрдВ рдпрд╛ рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рддреЛ рдЖрдЗрдП рд╕реЛрдЪреЗрдВ рдХрд┐ рд╡реЗ рдХреНрдпрд╛ рд╣реЛрдиреЗ рдЪрд╛рд╣рд┐рдПред рдЖрдкрдХреЛ рдХреБрд▓ рдорд┐рд▓рд╛рдХрд░ рдЪрд╛рд░ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред

  • рдЧреЗрдо рдкреНрд░рд╛рд░рдВрдн: рдореЗрдореЛрд░реАрдЧреЗрдордбрд┐рдбрд╕реНрдЯрд╛рд░реНрдЯред
  • рдЖрдкрдХреЛ рдХрд╛рд░реНрдб рдХреЛ рдиреАрдЪреЗ рдХреА рдУрд░ рдХрд░рдирд╛ рд╣реЛрдЧрд╛: рдореЗрдореЛрд░реАрдЧреЗрдорд╢реЛрдХрд╛рд░реНрдбреНрд╕ред
  • рдЖрдкрдХреЛ рдХрд╛рд░реНрдб рдХреЛ рдиреАрдЪреЗ рдХреА рдУрд░ рдХрд░рдирд╛ рд╣реЛрдЧрд╛: рдореЗрдореЛрд░реАрдЧреЗрдорд╣рд╛рдЗрдбрдХрд╛рд░реНрдбреНрд╕ред
  • рдЧреЗрдо рдХрд╛ рдЕрдВрдд: рдореЗрдореЛрд░реАрдЧреЗрдордбрд┐рдбрдПрдВрдбред

рд╕рднреА рдЪрд╛рд░ рддрд░реАрдХреЛрдВ рдХреЛ рдореБрдЦреНрдп рд╡рд░реНрдЧ рдХреЗ рд▓рд┐рдП рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЬреЛ рдЧреЗрдордХрдВрдЯреНрд░реЛрд▓рд░ рд╣реИред

рдореЗрдореЛрд░реАрдЧреЗрдордбрд┐рдбрд╕реНрдЯрд╛рд░реНрдЯ

рдЬрдм рдпрд╣ рд╡рд┐рдзрд┐ рдЪрд▓рд╛рдИ рдЬрд╛рддреА рд╣реИ, рддреЛ рдЧреЗрдо рд╢реБрд░реВ рд╣реЛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП (рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ PLAY рджрдмрд╛рддрд╛ рд╣реИ)ред рдпрд╣рд╛рдВ рд╣рдо рдмрд╕ CollectionView.reloadData() рдХреЛ рдХреЙрд▓ рдХрд░рдХреЗ рд╕рд╛рдордЧреНрд░реА рдХреЛ рдкреБрдирдГ рд▓реЛрдб рдХрд░реЗрдВрдЧреЗ, рдЬреЛ рдХрд╛рд░реНрдбреЛрдВ рдХреЛ рдлреЗрд░рдмрджрд▓ рдХрд░реЗрдЧрд╛ред

func memoryGameDidStart(_ game: MemoryGame) {
    collectionView.reloadData()
}

рдореЗрдореЛрд░реАрдЧреЗрдорд╢реЛрдХрд╛рд░реНрдбреНрд╕

рд╣рдо рдЗрд╕ рд╡рд┐рдзрд┐ рдХреЛ CollectionSDViewSelectItemAt рд╕реЗ рдХрд╣рддреЗ рд╣реИрдВред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ рдпрд╣ рдЪрдпрдирд┐рдд рдХрд╛рд░реНрдб рджрд┐рдЦрд╛рддрд╛ рд╣реИ. рдлрд┐рд░ рдпрд╣ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд╛рдВрдЪ рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдХрд╛рд░реНрдб рджрд┐рдЦрд╛рдП рдЧрдП рд╕рд░рдгреА рдореЗрдВ рдХреЛрдИ рдмреЗрдЬреЛрдбрд╝ рдХрд╛рд░реНрдб рд╣реИ (рдпрджрд┐ рджрд┐рдЦрд╛рдП рдЧрдП рдХрд╛рд░реНрдб рдХреА рд╕рдВрдЦреНрдпрд╛ рд╡рд┐рд╖рдо рд╣реИ)ред рдпрджрд┐ рдХреЛрдИ рд╣реИ, рддреЛ рдЪрдпрдирд┐рдд рдХрд╛рд░реНрдб рдХреА рддреБрд▓рдирд╛ рдЙрд╕рд╕реЗ рдХреА рдЬрд╛рддреА рд╣реИред рдпрджрд┐ рдЪрд┐рддреНрд░ рд╕рдорд╛рди рд╣реИрдВ, рддреЛ рджреЛрдиреЛрдВ рдХрд╛рд░реНрдб рджрд┐рдЦрд╛рдП рдЧрдП рдХрд╛рд░реНрдб рдореЗрдВ рдЬреЛрдбрд╝реЗ рдЬрд╛рддреЗ рд╣реИрдВ рдФрд░ рдКрдкрд░ рдХреА рдУрд░ рд░рд╣рддреЗ рд╣реИрдВред рдпрджрд┐ рднрд┐рдиреНрди рд╣реИ, рддреЛ рдХрд╛рд░реНрдб рджрд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛ рдХрд╛рд░реНрдб рдЫреЛрдбрд╝ рджреЗрддрд╛ рд╣реИ рдФрд░ рджреЛрдиреЛрдВ рдХреЛ рдиреАрдЪреЗ рдХреА рдУрд░ рдХрд░ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рдореЗрдореЛрд░реАрдЧреЗрдорд╣рд╛рдЗрдбрдХрд╛рд░реНрдбреНрд╕

рдпрджрд┐ рдХрд╛рд░реНрдб рдореЗрд▓ рдирд╣реАрдВ рдЦрд╛рддреЗ рд╣реИрдВ, рддреЛ рдЗрд╕ рд╡рд┐рдзрд┐ рдХреЛ рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдХрд╛рд░реНрдб рдХреА рдЫрд╡рд┐рдпрд╛рдВ рдЫрд┐рдкрд╛ рджреА рдЬрд╛рддреА рд╣реИрдВред

рджрд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛ = рдЭреВрдард╛.

рдореЗрдореЛрд░реАрдЧреЗрдордбрд┐рдбрдПрдВрдб

рдЬрдм рдЗрд╕ рдкрджреНрдзрддрд┐ рдХреЛ рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рд╕рднреА рдХрд╛рд░реНрдб рдкрд╣рд▓реЗ рд╣реА рд╕рд╛рдордиреЗ рдЖ рдЪреБрдХреЗ рд╣реИрдВ рдФрд░ рдХрд╛рд░реНрдбреЛрдВ рдХреА рджрд┐рдЦрд╛рдИ рдЧрдИ рд╕реВрдЪреА рдореЗрдВ рд╣реИрдВ: рдХрд╛рд░реНрдбреНрд╕рд╢реЛрди.рдХрд╛рдЙрдВрдЯ = рдХрд╛рд░реНрдбреНрд╕.рдХрд╛рдЙрдВрдЯ, рдЗрд╕рд▓рд┐рдП рдЦреЗрд▓ рдЦрддреНрдо рд╣реЛ рдЧрдпрд╛ рд╣реИред рд╡рд┐рдзрд┐ рдХреЛ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рддрдм рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрдм рд╣рдордиреЗ isPlaying var рдХреЛ рдЧрд▓рдд рдкрд░ рд╕реЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП EndGame() рдХреЛ рдХреЙрд▓ рдХрд┐рдпрд╛ рд╣реИ, рдЬрд┐рд╕рдХреЗ рдмрд╛рдж рдЧреЗрдо рдХрд╛ рдЕрдВрдд рд╕рдВрджреЗрд╢ рджрд┐рдЦрд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдЕрд▓рд░реНрдЯрдХрдВрдЯреНрд░реЛрд▓рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд┐рдпрдВрддреНрд░рдХ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдВрдХреЗрддрдХ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред viewDidDisappear рдХреЛ рдХреЙрд▓ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдЧреЗрдо рд░реАрд╕реЗрдЯ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред

рдЧреЗрдордХрдВрдЯреНрд░реЛрд▓рд░ рдореЗрдВ рдпрд╣ рд╕рдм рдХреБрдЫ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рджрд┐рдЦрддрд╛ рд╣реИ:

extension GameController: MemoryGameProtocol {
    func memoryGameDidStart(_ game: MemoryGame) {
        collectionView.reloadData()
    }
 
 
    func memoryGame(_ game: MemoryGame, showCards cards: [Card]) {
        for card in cards {
            guard let index = game.indexForCard(card)
                else { continue
            }        
            
            let cell = collectionView.cellForItem(
                at: IndexPath(item: index, section:0)
            ) as! CardCell
 
            cell.showCard(true, animted: true)
        }
    }
 
    func memoryGame(_ game: MemoryGame, hideCards cards: [Card]) {
        for card in cards {
            guard let index = game.indexForCard(card)
                else { continue
            }
            
            let cell = collectionView.cellForItem(
                at: IndexPath(item: index, section:0)
            ) as! CardCell
    
            cell.showCard(false, animted: true)
        }
    }
 
    func memoryGameDidEnd(_ game: MemoryGame) {
        let alertController = UIAlertController(
            title: defaultAlertTitle,
            message: defaultAlertMessage,
            preferredStyle: .alert
        )
 
        let cancelAction = UIAlertAction(
            title: "Nah", style: .cancel) {
            [weak self] (action) in
            self?.collectionView.isHidden = true
        }
 
        let playAgainAction = UIAlertAction(
            title: "Dale!", style: .default) {
            [weak self] (action) in
            self?.collectionView.isHidden = true
 
            self?.resetGame()
        }
 
        alertController.addAction(cancelAction)
        alertController.addAction(playAgainAction)
        
        self.present(alertController, animated: true) { }
    
        resetGame()
    }
}

рд╕реНрд╡рд┐рдлреНрдЯ рдореЗрдВ рдореЗрдореЛрд░реА рдХрд╛рд░реНрдб рдЧреЗрдо рд▓рд┐рдЦрдирд╛
рджрд░рдЕрд╕рд▓, рдмрд╕ рдЗрддрдирд╛ рд╣реА. рдЖрдк рдЧреЗрдо рдХрд╛ рдЕрдкрдирд╛ рд╕рдВрд╕реНрдХрд░рдг рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рд╣реИрдкреНрдкреА рдХреЛрдбрд┐рдВрдЧ!

рд╕реНрдХрд┐рд▓рдмреЙрдХреНрд╕ рдЕрдиреБрд╢рдВрд╕рд╛ рдХрд░рддрд╛ рд╣реИ:

рд╕реНрд░реЛрдд: www.habr.com

рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдЬреЛрдбрд╝реЗрдВ