ПисанС Π½Π° ΠΈΠ³Ρ€Π° с ΠΊΠ°Ρ€Ρ‚ΠΈ с ΠΏΠ°ΠΌΠ΅Ρ‚ Π² Swift

ПисанС Π½Π° ΠΈΠ³Ρ€Π° с ΠΊΠ°Ρ€Ρ‚ΠΈ с ΠΏΠ°ΠΌΠ΅Ρ‚ Π² Swift

Π’Π°Π·ΠΈ статия описва процСса Π½Π° създаванС Π½Π° проста ΠΈΠ³Ρ€Π° Π·Π° Ρ‚Ρ€Π΅Π½ΠΈΡ€Π°Π½Π΅ Π½Π° ΠΏΠ°ΠΌΠ΅Ρ‚Ρ‚Π°, която наистина харСсвам. ОсвСн Ρ‡Π΅ Π΅ Π΄ΠΎΠ±ΡŠΡ€ сам ΠΏΠΎ сСбС си, Ρ‰Π΅ Π½Π°ΡƒΡ‡ΠΈΡ‚Π΅ ΠΌΠ°Π»ΠΊΠΎ ΠΏΠΎΠ²Π΅Ρ‡Π΅ Π·Π° класовСтС ΠΈ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»ΠΈΡ‚Π΅ Π½Π° Swift, Π΄ΠΎΠΊΠ°Ρ‚ΠΎ Π²ΡŠΡ€Π²ΠΈΡ‚Π΅. Но ΠΏΡ€Π΅Π΄ΠΈ Π΄Π° Π·Π°ΠΏΠΎΡ‡Π½Π΅ΠΌ, Π½Π΅ΠΊΠ° Ρ€Π°Π·Π±Π΅Ρ€Π΅ΠΌ самата ΠΈΠ³Ρ€Π°.

НапомнямС Π²ΠΈ: Π·Π° всички Ρ‡ΠΈΡ‚Π°Ρ‚Π΅Π»ΠΈ Π½Π° "Habr" - ΠΎΡ‚ΡΡ‚ΡŠΠΏΠΊΠ° ΠΎΡ‚ 10 000 Ρ€ΡƒΠ±Π»ΠΈ ΠΏΡ€ΠΈ записванС във всСки курс Skillbox, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΠΊΠΈ промоционалния ΠΊΠΎΠ΄ Π½Π° "Habr".

Skillbox ΠΏΡ€Π΅ΠΏΠΎΡ€ΡŠΡ‡Π²Π°: ΠžΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅Π½ ΠΎΠ½Π»Π°ΠΉΠ½ курс β€žΠŸΡ€ΠΎΡ„Π΅ΡΠΈΡ Java Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊβ€œ.

Как сС ΠΈΠ³Ρ€Π°Π΅ ΠΊΠ°Ρ€Ρ‚Π° с ΠΏΠ°ΠΌΠ΅Ρ‚

Π˜Π³Ρ€Π°Ρ‚Π° Π·Π°ΠΏΠΎΡ‡Π²Π° с дСмонстрация Π½Π° Π½Π°Π±ΠΎΡ€ ΠΎΡ‚ ΠΊΠ°Ρ€Ρ‚ΠΈ. Π›Π΅ΠΆΠ°Ρ‚ с Π»ΠΈΡ†Π΅Ρ‚ΠΎ Π½Π°Π΄ΠΎΠ»Ρƒ (ΡΡŠΠΎΡ‚Π²Π΅Ρ‚Π½ΠΎ ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅Ρ‚ΠΎ Π½Π°Π΄ΠΎΠ»Ρƒ). ΠšΠΎΠ³Π°Ρ‚ΠΎ Ρ‰Ρ€Π°ΠΊΠ½Π΅Ρ‚Π΅ Π²ΡŠΡ€Ρ…Ρƒ ΠΊΠΎΠΉΡ‚ΠΎ ΠΈ Π΄Π° Π΅, ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅Ρ‚ΠΎ сС отваря Π·Π° няколко сСкунди.

Π—Π°Π΄Π°Ρ‡Π°Ρ‚Π° Π½Π° ΠΈΠ³Ρ€Π°Ρ‡Π° Π΅ Π΄Π° Π½Π°ΠΌΠ΅Ρ€ΠΈ всички ΠΊΠ°Ρ€Ρ‚ΠΈ с Π΅Π΄Π½Π°ΠΊΠ²ΠΈ ΠΊΠ°Ρ€Ρ‚ΠΈΠ½ΠΊΠΈ. Ако слСд ΠΊΠ°Ρ‚ΠΎ ΠΎΡ‚Π²ΠΎΡ€ΠΈΡ‚Π΅ ΠΏΡŠΡ€Π²Π°Ρ‚Π° ΠΊΠ°Ρ€Ρ‚Π°, ΠΎΠ±ΡŠΡ€Π½Π΅Ρ‚Π΅ Π²Ρ‚ΠΎΡ€Π°Ρ‚Π° ΠΈ ΠΊΠ°Ρ€Ρ‚ΠΈΠ½ΠΊΠΈΡ‚Π΅ ΡΡŠΠ²ΠΏΠ°Π΄Π½Π°Ρ‚, Π΄Π²Π΅Ρ‚Π΅ ΠΊΠ°Ρ€Ρ‚ΠΈ остават ΠΎΡ‚Π²ΠΎΡ€Π΅Π½ΠΈ. Ако Π½Π΅ ΡΡŠΠ²ΠΏΠ°Π΄Π°Ρ‚, ΠΊΠ°Ρ€Ρ‚ΠΈΡ‚Π΅ сС затварят ΠΎΡ‚Π½ΠΎΠ²ΠΎ. Π¦Π΅Π»Ρ‚Π° Π΅ Π΄Π° сС ΠΎΡ‚Π²ΠΎΡ€ΠΈ всичко.

Π‘Ρ‚Ρ€ΡƒΠΊΡ‚ΡƒΡ€Π° Π½Π° ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°

Π—Π° Π΄Π° ΡΡŠΠ·Π΄Π°Π΄Π΅Ρ‚Π΅ проста вСрсия Π½Π° Ρ‚Π°Π·ΠΈ ΠΈΠ³Ρ€Π°, ΠΈΠΌΠ°Ρ‚Π΅ Π½ΡƒΠΆΠ΄Π° ΠΎΡ‚ слСднитС ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΈ:

  • Π•Π΄ΠΈΠ½ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π΅Ρ€: GameController.swift.
  • Π•Π΄ΠΈΠ½ ΠΈΠ·Π³Π»Π΅Π΄: CardCell.swift.
  • Π”Π²Π° ΠΌΠΎΠ΄Π΅Π»Π°: MemoryGame.swift ΠΈ Card.swift.
  • Main.storyboard, Π·Π° Π΄Π° сС Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€Π°, Ρ‡Π΅ цСлият Π½Π°Π±ΠΎΡ€ ΠΎΡ‚ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΈ Π΅ Π½Π°Π»ΠΈΡ‡Π΅Π½.

Π—Π°ΠΏΠΎΡ‡Π²Π°ΠΌΠ΅ с Π½Π°ΠΉ-простия ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ Π½Π° ΠΈΠ³Ρ€Π°Ρ‚Π°, ΠΊΠ°Ρ€Ρ‚ΠΈΡ‚Π΅.

Card.swift

ΠœΠΎΠ΄Π΅Π»ΡŠΡ‚ Π½Π° ΠΊΠ°Ρ€Ρ‚Π°Ρ‚Π° Ρ‰Π΅ ΠΈΠΌΠ° Ρ‚Ρ€ΠΈ свойства: id Π·Π° ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΡ†ΠΈΡ€Π°Π½Π΅ Π½Π° всяка Π΅Π΄Π½Π°, ΠΏΠΎΠΊΠ°Π·Π°Π½Π° Π±ΡƒΠ»Π΅Π²Π° ΠΏΡ€ΠΎΠΌΠ΅Π½Π»ΠΈΠ²Π°, Π·Π° Π΄Π° ΡƒΡ‚ΠΎΡ‡Π½ΠΈ статуса Π½Π° ΠΊΠ°Ρ€Ρ‚Π°Ρ‚Π° (скрита ΠΈΠ»ΠΈ ΠΎΡ‚Π²ΠΎΡ€Π΅Π½Π°) ΠΈ artworkURL Π·Π° изобраТСнията Π½Π° ΠΊΠ°Ρ€Ρ‚ΠΈΡ‚Π΅.

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

Π©Π΅ Π²ΠΈ трябват ΠΈ Ρ‚Π΅Π·ΠΈ ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΈ, Π·Π° Π΄Π° ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»ΠΈΡ€Π°Ρ‚Π΅ взаимодСйствиСто Π½Π° ΠΏΠΎΡ‚Ρ€Π΅Π±ΠΈΡ‚Π΅Π»ΠΈΡ‚Π΅ с ΠΊΠ°Ρ€Ρ‚ΠΈΡ‚Π΅:

ΠœΠ΅Ρ‚ΠΎΠ΄ Π·Π° ΠΏΠΎΠΊΠ°Π·Π²Π°Π½Π΅ Π½Π° ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ Π²ΡŠΡ€Ρ…Ρƒ ΠΊΠ°Ρ€Ρ‚Π°. Π’ΡƒΠΊ Π½ΡƒΠ»ΠΈΡ€Π°ΠΌΠ΅ всички свойства ΠΏΠΎ ΠΏΠΎΠ΄Ρ€Π°Π·Π±ΠΈΡ€Π°Π½Π΅. Π—Π° id Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π°ΠΌΠ΅ случаСн id Ρ‡Ρ€Π΅Π· ΠΈΠ·Π²ΠΈΠΊΠ²Π°Π½Π΅ Π½Π° 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    
}

И ΠΎΡ‰Π΅ Π΅Π΄ΠΈΠ½ ΠΌΠ΅Ρ‚ΠΎΠ΄ Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌ Π·Π° Ρ€Π°Π·Π±ΡŠΡ€ΠΊΠ²Π°Π½Π΅ Π½Π° ΠΊΠ°Ρ€Ρ‚ΠΈΡ‚Π΅ Π² Π½Π°Ρ‡Π°Π»ΠΎΡ‚ΠΎ. Π©Π΅ Π³ΠΎ Π½Π°ΠΏΡ€Π°Π²ΠΈΠΌ Ρ€Π°Π·ΡˆΠΈΡ€Π΅Π½ΠΈΠ΅ Π½Π° класа Array.

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

А Π΅Ρ‚ΠΎ ΠΈ имплСмСнтацията Π½Π° ΠΊΠΎΠ΄Π° Π·Π° ΠΌΠΎΠ΄Π΅Π»Π° Card с всички свойства ΠΈ ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΈ.

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

ΠŸΡ€ΠΎΠ΄ΡŠΠ»ΠΆΠ°Π²Π°ΠΉ.

Вторият ΠΌΠΎΠ΄Π΅Π» Π΅ MemoryGame, Ρ‚ΡƒΠΊ смС Π·Π°Π΄Π°Π»ΠΈ Ρ€Π΅ΡˆΠ΅Ρ‚ΠΊΠ° 4*4. ΠœΠΎΠ΄Π΅Π»ΡŠΡ‚ Ρ‰Π΅ ΠΈΠΌΠ° свойства ΠΊΠ°Ρ‚ΠΎ ΠΊΠ°Ρ€Ρ‚ΠΈ (масив ΠΎΡ‚ ΠΊΠ°Ρ€Ρ‚ΠΈ Π² Ρ€Π΅ΡˆΠ΅Ρ‚ΠΊΠ°), масив cardsShown с Π²Π΅Ρ‡Π΅ ΠΎΡ‚Π²ΠΎΡ€Π΅Π½ΠΈ ΠΊΠ°Ρ€Ρ‚ΠΈ ΠΈ Π±ΡƒΠ»Π΅Π²Π° ΠΏΡ€ΠΎΠΌΠ΅Π½Π»ΠΈΠ²Π° isPlaying Π·Π° прослСдяванС Π½Π° ΡΡŠΡΡ‚ΠΎΡΠ½ΠΈΠ΅Ρ‚ΠΎ Π½Π° ΠΈΠ³Ρ€Π°Ρ‚Π°.

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 Π½Π° true.

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

Ако искамС Π΄Π° рСстартирамС ΠΈΠ³Ρ€Π°Ρ‚Π°, слСд Ρ‚ΠΎΠ²Π° Π·Π°Π΄Π°Π²Π°ΠΌΠ΅ ΠΏΡ€ΠΎΠΌΠ΅Π½Π»ΠΈΠ²Π°Ρ‚Π° isPlaying Π½Π° false ΠΈ ΠΏΡ€Π΅ΠΌΠ°Ρ…Π²Π°ΠΌΠ΅ ΠΏΡŠΡ€Π²ΠΎΠ½Π°Ρ‡Π°Π»Π½ΠΎΡ‚ΠΎ ΠΎΡ„ΠΎΡ€ΠΌΠ»Π΅Π½ΠΈΠ΅ Π½Π° ΠΊΠ°Ρ€Ρ‚ΠΈΡ‚Π΅.

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
}

Π’ΠΎΠ·ΠΈ ΠΌΠ΅Ρ‚ΠΎΠ΄ Ρ‡Π΅Ρ‚Π΅ послСдния Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚ Π² масива **cardsShown** ΠΈ Π²Ρ€ΡŠΡ‰Π° Π½Π΅ΡΡŠΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²Π°Ρ‰Π°Ρ‚Π° ΠΊΠ°Ρ€Ρ‚Π°.

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 ΠΈΠ·Π³Π»Π΅ΠΆΠ΄Π° ΠΏΠΎ слСдния Π½Π°Ρ‡ΠΈΠ½:

ПисанС Π½Π° ΠΈΠ³Ρ€Π° с ΠΊΠ°Ρ€Ρ‚ΠΈ с ΠΏΠ°ΠΌΠ΅Ρ‚ Π² Swift

ΠŸΡŠΡ€Π²ΠΎΠ½Π°Ρ‡Π°Π»Π½ΠΎ трябва Π΄Π° Π·Π°Π΄Π°Π΄Π΅Ρ‚Π΅ Π½ΠΎΠ²Π°Ρ‚Π° ΠΈΠ³Ρ€Π° ΠΊΠ°Ρ‚ΠΎ viewDidLoad Π² ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π΅Ρ€Π°, Π²ΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅Π»Π½ΠΎ изобраТСнията Π·Π° ΠΌΡ€Π΅ΠΆΠ°Ρ‚Π°. Π’ ΠΈΠ³Ρ€Π°Ρ‚Π° всичко Ρ‚ΠΎΠ²Π° Ρ‰Π΅ бъдС прСдставСно ΠΎΡ‚ 4*4 collectionView. Ако всС ΠΎΡ‰Π΅ Π½Π΅ стС Π·Π°ΠΏΠΎΠ·Π½Π°Ρ‚ΠΈ с collectionView, Π΅Ρ‚ΠΎ Π³ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠ°Ρ‚Π° информация.

НиС Ρ‰Π΅ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€Π°ΠΌΠ΅ GameController ΠΊΠ°Ρ‚ΠΎ основСн ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π΅Ρ€ Π½Π° ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅Ρ‚ΠΎ. GameController Ρ‰Π΅ ΠΈΠΌΠ° collectionView, ΠΊΠΎΠΉΡ‚ΠΎ Ρ‰Π΅ Π½Π°Ρ€ΠΈΡ‡Π°ΠΌΠ΅ IBOutlet. Π”Ρ€ΡƒΠ³Π° ΠΏΡ€Π΅ΠΏΡ€Π°Ρ‚ΠΊΠ° Π΅ към Π±ΡƒΡ‚ΠΎΠ½Π° IBAction onStartGame(), Ρ‚ΠΎΠ²Π° Π΅ UIButton, ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° Π³ΠΎ Π²ΠΈΠ΄ΠΈΡ‚Π΅ Π² сцСнария, Π½Π°Ρ€Π΅Ρ‡Π΅Π½ PLAY.

Малко Π·Π° внСдряванСто Π½Π° ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π΅Ρ€ΠΈ:

  • ΠŸΡŠΡ€Π²ΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€Π°ΠΌΠ΅ Π΄Π²Π° основни ΠΎΠ±Π΅ΠΊΡ‚Π° - ΠΌΡ€Π΅ΠΆΠ°Ρ‚Π°: game = MemoryGame() ΠΈ Π½Π°Π±ΠΎΡ€ ΠΎΡ‚ ΠΊΠ°Ρ€Ρ‚ΠΈ: cards = [Card]().
  • Π—Π°Π΄Π°Π²Π°ΠΌΠ΅ ΠΏΡŠΡ€Π²ΠΎΠ½Π°Ρ‡Π°Π»Π½ΠΈΡ‚Π΅ ΠΏΡ€ΠΎΠΌΠ΅Π½Π»ΠΈΠ²ΠΈ ΠΊΠ°Ρ‚ΠΎ viewDidLoad, Ρ‚ΠΎΠ²Π° Π΅ ΠΏΡŠΡ€Π²ΠΈΡΡ‚ ΠΌΠ΅Ρ‚ΠΎΠ΄, ΠΊΠΎΠΉΡ‚ΠΎ сС ΠΈΠ·Π²ΠΈΠΊΠ²Π°, Π΄ΠΎΠΊΠ°Ρ‚ΠΎ ΠΈΠ³Ρ€Π°Ρ‚Π° Ρ€Π°Π±ΠΎΡ‚ΠΈ.
  • collectionView Π΅ настроСн Π½Π° скрит, Π·Π°Ρ‰ΠΎΡ‚ΠΎ всички ΠΊΠ°Ρ€Ρ‚ΠΈ са скрити, Π΄ΠΎΠΊΠ°Ρ‚ΠΎ потрСбитСлят Π½Π΅ натиснС PLAY.
  • Π’Π΅Π΄Π½Π°Π³Π° слСд ΠΊΠ°Ρ‚ΠΎ натиснСм PLAY, сСкцията onStartGame IBAction Π·Π°ΠΏΠΎΡ‡Π²Π° ΠΈ Π½ΠΈΠ΅ Π·Π°Π΄Π°Π²Π°ΠΌΠ΅ свойството collectionView isHidden Π½Π° false, Ρ‚Π°ΠΊΠ° Ρ‡Π΅ ΠΊΠ°Ρ€Ρ‚ΠΈΡ‚Π΅ Π΄Π° ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° станат Π²ΠΈΠ΄ΠΈΠΌΠΈ.
  • ВсСки ΠΏΡŠΡ‚, ΠΊΠΎΠ³Π°Ρ‚ΠΎ потрСбитСлят ΠΈΠ·Π±Π΅Ρ€Π΅ ΠΊΠ°Ρ€Ρ‚Π°, сС ΠΈΠ·Π²ΠΈΠΊΠ²Π° ΠΌΠ΅Ρ‚ΠΎΠ΄ΡŠΡ‚ didSelectItemAt. Π’ ΠΌΠ΅Ρ‚ΠΎΠ΄Π°, ΠΊΠΎΠΉΡ‚ΠΎ ΠΈΠ·Π²ΠΈΠΊΠ²Π°ΠΌΠ΅ didSelectCard, Π·Π° Π΄Π° Ρ€Π΅Π°Π»ΠΈΠ·ΠΈΡ€Π°ΠΌΠ΅ основната Π»ΠΎΠ³ΠΈΠΊΠ° Π½Π° ΠΈΠ³Ρ€Π°Ρ‚Π°.

Π•Ρ‚ΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Ρ‚Π΅Π»Π½ΠΎΡ‚ΠΎ внСдряванС Π½Π° GameController:

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

Π‘Π΅Π³Π° Π½Π΅ΠΊΠ° ΠΏΠΎΠ³ΠΎΠ²ΠΎΡ€ΠΈΠΌ ΠΌΠ°Π»ΠΊΠΎ Π·Π° Π²Π°ΠΆΠ½ΠΈΡ‚Π΅ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»ΠΈ.

ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»ΠΈ

Π Π°Π±ΠΎΡ‚Π°Ρ‚Π° с ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»ΠΈ Π΅ ядрото Π½Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ€Π°Π½Π΅Ρ‚ΠΎ Π½Π° Swift. ΠŸΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»ΠΈΡ‚Π΅ прСдоставят Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ Π·Π° Π΄Π΅Ρ„ΠΈΠ½ΠΈΡ€Π°Π½Π΅ Π½Π° ΠΏΡ€Π°Π²ΠΈΠ»Π° Π·Π° клас, структура ΠΈΠ»ΠΈ изброяванС. Π’ΠΎΠ·ΠΈ ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏ Π²ΠΈ позволява Π΄Π° ΠΏΠΈΡˆΠ΅Ρ‚Π΅ ΠΌΠΎΠ΄ΡƒΠ»Π΅Π½ ΠΈ Ρ€Π°Π·ΡˆΠΈΡ€ΡΠ΅ΠΌ ΠΊΠΎΠ΄. Π’ΡΡŠΡ‰Π½ΠΎΡΡ‚ Ρ‚ΠΎΠ²Π° Π΅ ΠΌΠΎΠ΄Π΅Π», ΠΊΠΎΠΉΡ‚ΠΎ Π²Π΅Ρ‡Π΅ ΠΏΡ€ΠΈΠ»Π°Π³Π°ΠΌΠ΅ Π·Π° collectionView Π² GameController. Π‘Π΅Π³Π° Π½Π΅ΠΊΠ° Π½Π°ΠΏΡ€Π°Π²ΠΈΠΌ наша собствСна вСрсия. Π‘ΠΈΠ½Ρ‚Π°ΠΊΡΠΈΡΡŠΡ‚ Ρ‰Π΅ ΠΈΠ·Π³Π»Π΅ΠΆΠ΄Π° Ρ‚Π°ΠΊΠ°:

protocol MemoryGameProtocol {
    //protocol definition goes here
}

Π—Π½Π°Π΅ΠΌ, Ρ‡Π΅ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»ΡŠΡ‚ Π½ΠΈ позволява Π΄Π° Π΄Π΅Ρ„ΠΈΠ½ΠΈΡ€Π°ΠΌΠ΅ ΠΏΡ€Π°Π²ΠΈΠ»Π° ΠΈΠ»ΠΈ инструкции Π·Π° внСдряванС Π½Π° клас, Ρ‚Π°ΠΊΠ° Ρ‡Π΅ Π½Π΅ΠΊΠ° помислим ΠΊΠ°ΠΊΠ²ΠΈ трябва Π΄Π° Π±ΡŠΠ΄Π°Ρ‚ Ρ‚Π΅. Врябват Π²ΠΈ ΠΎΠ±Ρ‰ΠΎ Ρ‡Π΅Ρ‚ΠΈΡ€ΠΈ.

  • Начало Π½Π° ΠΈΠ³Ρ€Π°Ρ‚Π°: memoryGameDidStart.
  • Врябва Π΄Π° ΠΎΠ±ΡŠΡ€Π½Π΅Ρ‚Π΅ ΠΊΠ°Ρ€Ρ‚Π°Ρ‚Π° с Π»ΠΈΡ†Π΅Ρ‚ΠΎ Π½Π°Π΄ΠΎΠ»Ρƒ: memoryGameShowCards.
  • Врябва Π΄Π° ΠΎΠ±ΡŠΡ€Π½Π΅Ρ‚Π΅ ΠΊΠ°Ρ€Ρ‚Π°Ρ‚Π° с Π»ΠΈΡ†Π΅Ρ‚ΠΎ Π½Π°Π΄ΠΎΠ»Ρƒ: memoryGameHideCards.
  • ΠšΡ€Π°ΠΉ Π½Π° ΠΈΠ³Ρ€Π°Ρ‚Π°: memoryGameDidEnd.

И Ρ‡Π΅Ρ‚ΠΈΡ€ΠΈΡ‚Π΅ ΠΌΠ΅Ρ‚ΠΎΠ΄Π° ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° Π±ΡŠΠ΄Π°Ρ‚ Ρ€Π΅Π°Π»ΠΈΠ·ΠΈΡ€Π°Π½ΠΈ Π·Π° основния клас, ΠΊΠΎΠΉΡ‚ΠΎ Π΅ GameController.

memoryGameDidStart

ΠšΠΎΠ³Π°Ρ‚ΠΎ Ρ‚ΠΎΠ·ΠΈ ΠΌΠ΅Ρ‚ΠΎΠ΄ сС изпълни, ΠΈΠ³Ρ€Π°Ρ‚Π° трябва Π΄Π° Π·Π°ΠΏΠΎΡ‡Π½Π΅ (потрСбитСлят натиска PLAY). Π’ΡƒΠΊ просто Ρ‰Π΅ ΠΏΡ€Π΅Π·Π°Ρ€Π΅Π΄ΠΈΠΌ ΡΡŠΠ΄ΡŠΡ€ΠΆΠ°Π½ΠΈΠ΅Ρ‚ΠΎ, ΠΊΠ°Ρ‚ΠΎ ΠΈΠ·Π²ΠΈΠΊΠ°ΠΌΠ΅ collectionView.reloadData(), ΠΊΠΎΠ΅Ρ‚ΠΎ Ρ‰Π΅ Ρ€Π°Π·Π±ΡŠΡ€ΠΊΠ° ΠΊΠ°Ρ€Ρ‚ΠΈΡ‚Π΅.

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

memoryGameShowCards

ИзвиквамС Ρ‚ΠΎΠ·ΠΈ ΠΌΠ΅Ρ‚ΠΎΠ΄ ΠΎΡ‚ collectionSDViewSelectItemAt. ΠŸΡŠΡ€Π²ΠΎ ΠΏΠΎΠΊΠ°Π·Π²Π° ΠΈΠ·Π±Ρ€Π°Π½Π°Ρ‚Π° ΠΊΠ°Ρ€Ρ‚Π°. Π‘Π»Π΅Π΄ Ρ‚ΠΎΠ²Π° провСрява Π΄Π°Π»ΠΈ ΠΈΠΌΠ° Π½Π΅ΡΡŠΠ²ΠΏΠ°Π΄Π°Ρ‰Π° ΠΊΠ°Ρ€Ρ‚Π° Π² масива cardsShown (Π°ΠΊΠΎ броят Π½Π° cardsShown Π΅ Π½Π΅Ρ‡Π΅Ρ‚Π΅Π½). Ако ΠΈΠΌΠ° Ρ‚Π°ΠΊΠ°Π²Π°, ΠΈΠ·Π±Ρ€Π°Π½Π°Ρ‚Π° ΠΊΠ°Ρ€Ρ‚Π° сС сравнява с нСя. Ако снимкитС са Π΅Π΄Π½Π°ΠΊΠ²ΠΈ, Π΄Π²Π΅Ρ‚Π΅ ΠΊΠ°Ρ€Ρ‚ΠΈ сС добавят към cardsShown ΠΈ остават с Π»ΠΈΡ†Π΅Ρ‚ΠΎ Π½Π°Π³ΠΎΡ€Π΅. Ако Π΅ Ρ€Π°Π·Π»ΠΈΡ‡Π½Π°, ΠΊΠ°Ρ€Ρ‚Π°Ρ‚Π° оставя ΠΊΠ°Ρ€Ρ‚ΠΈΡ‚Π΅ Показани ΠΈ Π΄Π²Π΅Ρ‚Π΅ сС ΠΎΠ±Ρ€ΡŠΡ‰Π°Ρ‚ с Π»ΠΈΡ†Π΅Ρ‚ΠΎ Π½Π°Π΄ΠΎΠ»Ρƒ.

memoryGameHideCards

Ако ΠΊΠ°Ρ€Ρ‚ΠΈΡ‚Π΅ Π½Π΅ ΡΡŠΠ²ΠΏΠ°Π΄Π°Ρ‚, Ρ‚ΠΎΠ·ΠΈ ΠΌΠ΅Ρ‚ΠΎΠ΄ сС ΠΈΠ·Π²ΠΈΠΊΠ²Π° ΠΈ изобраТСнията Π½Π° ΠΊΠ°Ρ€Ρ‚ΠΈΡ‚Π΅ сС скриват.

ΠΏΠΎΠΊΠ°Π·Π°Π½ΠΎ = нСвярно.

memoryGameDidEnd

ΠšΠΎΠ³Π°Ρ‚ΠΎ Ρ‚ΠΎΠ·ΠΈ ΠΌΠ΅Ρ‚ΠΎΠ΄ бъдС ΠΈΠ·Π²ΠΈΠΊΠ°Π½, Ρ‚ΠΎΠ²Π° ΠΎΠ·Π½Π°Ρ‡Π°Π²Π°, Ρ‡Π΅ всички ΠΊΠ°Ρ€Ρ‚ΠΈ Π²Π΅Ρ‡Π΅ са Ρ€Π°Π·ΠΊΡ€ΠΈΡ‚ΠΈ ΠΈ са Π² списъка cardsShown: cardsShown.count = cards.count, Ρ‚Π°ΠΊΠ° Ρ‡Π΅ ΠΈΠ³Ρ€Π°Ρ‚Π° Π΅ ΠΏΡ€ΠΈΠΊΠ»ΡŽΡ‡ΠΈΠ»Π°. ΠœΠ΅Ρ‚ΠΎΠ΄ΡŠΡ‚ сС ΠΈΠ·Π²ΠΈΠΊΠ²Π° спСциално, слСд ΠΊΠ°Ρ‚ΠΎ смС ΠΈΠ·Π²ΠΈΠΊΠ°Π»ΠΈ endGame(), Π·Π° Π΄Π° Π·Π°Π΄Π°Π΄Π΅ΠΌ isPlaying var Π½Π° false, слСд ΠΊΠΎΠ΅Ρ‚ΠΎ сС ΠΏΠΎΠΊΠ°Π·Π²Π° ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅Ρ‚ΠΎ Π·Π° ΠΊΡ€Π°ΠΉ Π½Π° ΠΈΠ³Ρ€Π°Ρ‚Π°. Π‘ΡŠΡ‰ΠΎ Ρ‚Π°ΠΊΠ° alertController сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° ΠΊΠ°Ρ‚ΠΎ ΠΈΠ½Π΄ΠΈΠΊΠ°Ρ‚ΠΎΡ€ Π·Π° ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π΅Ρ€Π°. viewDidDisappear сС ΠΈΠ·Π²ΠΈΠΊΠ²Π° ΠΈ ΠΈΠ³Ρ€Π°Ρ‚Π° сС Π½ΡƒΠ»ΠΈΡ€Π°.

Π•Ρ‚ΠΎ ΠΊΠ°ΠΊ ΠΈΠ·Π³Π»Π΅ΠΆΠ΄Π° всичко Ρ‚ΠΎΠ²Π° Π² GameController:

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

ПисанС Π½Π° ΠΈΠ³Ρ€Π° с ΠΊΠ°Ρ€Ρ‚ΠΈ с ΠΏΠ°ΠΌΠ΅Ρ‚ Π² Swift
Π’ΡΡŠΡ‰Π½ΠΎΡΡ‚ Ρ‚ΠΎΠ²Π° Π΅ всичко. ΠœΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅ Ρ‚ΠΎΠ·ΠΈ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚, Π·Π° Π΄Π° ΡΡŠΠ·Π΄Π°Π΄Π΅Ρ‚Π΅ своя собствСна вСрсия Π½Π° ΠΈΠ³Ρ€Π°Ρ‚Π°.

ΠŸΡ€ΠΈΡΡ‚Π½ΠΎ ΠΊΠΎΠ΄ΠΈΡ€Π°Π½Π΅!

Skillbox ΠΏΡ€Π΅ΠΏΠΎΡ€ΡŠΡ‡Π²Π°:

Π˜Π·Ρ‚ΠΎΡ‡Π½ΠΈΠΊ: www.habr.com

ДобавянС Π½Π° Π½ΠΎΠ² ΠΊΠΎΠΌΠ΅Π½Ρ‚Π°Ρ€