ืฉืจื™ื™ื‘ืŸ ืึท ื–ื›ึผืจื•ืŸ ืงืึทืจื“ืก ืฉืคึผื™ืœ ืื™ืŸ ืกื•ื•ื™ืคื˜

ืฉืจื™ื™ื‘ืŸ ืึท ื–ื›ึผืจื•ืŸ ืงืึทืจื“ืก ืฉืคึผื™ืœ ืื™ืŸ ืกื•ื•ื™ืคื˜

ื“ืขืจ ืึทืจื˜ื™ืงืœ ื‘ืืฉืจื™ื™ื‘ื˜ ื“ืขื ืคึผืจืึธืฆืขืก ืคื•ืŸ ืงืจื™ื™ื™ื˜ื™ื ื’ ืึท ืคึผืฉื•ื˜ ื–ื›ึผืจื•ืŸ ื˜ืจื™ื™ื ื™ื ื’ ืฉืคึผื™ืœ ื•ื•ืึธืก ืื™ืš ื˜ืึทืงืข ื•ื•ื™. ืึทื—ื•ืฅ ื–ื™ื™ืŸ ื’ื•ื˜ ืื™ืŸ ื–ื™ืš, ืื™ืจ ื•ื•ืขื˜ ืœืขืจื ืขืŸ ืึท ื‘ื™ืกืœ ืžืขืจ ื•ื•ืขื’ืŸ ืกื•ื•ื™ืคื˜ ืงืœืืกืŸ ืื•ืŸ ืคึผืจืึธื˜ืึธืงืึธืœืก ื•ื•ื™ ืื™ืจ ื’ื™ื™ืŸ. ืื‘ืขืจ ืื™ื™ื“ืขืจ ืžื™ืจ ืึธื ื”ื™ื™ื‘ืŸ, ืœืึธื–ืŸ ืื•ื ื“ื– ืคึฟืึทืจืฉื˜ื™ื™ืŸ ื“ื™ ืฉืคึผื™ืœ ื–ื™ืš.

ืžื™ืจ ื“ืขืจืžืึธื ืขืŸ ืื™ืจ: ืคึฟืึทืจ ืึทืœืข ืœื™ื™ืขื ืขืจ ืคื•ืŸ "ื”ื‘ืจ" - ืึท ืึทืจืึธืคึผืจืขื›ืขื ืขืŸ ืคื•ืŸ 10 ืจื•ื‘ืœ ื•ื•ืขืŸ ืื™ืจ ืคืึทืจืฉืจื™ื™ึทื‘ืŸ ืื™ืŸ ืงื™ื™ืŸ ืกืงื™ืœื‘ืึธืงืก ืงื•ืจืก ื ื™ืฆืŸ ื“ื™ ืคึผืขืจืžืึธื•ืฉืึทื ืึทืœ ืงืึธื“ "ื”ื‘ืจ".

Skillbox ืจืขืงืึทืžืขื ื“ื–: ื‘ื™ืœื“ื•ื ื’ืงืจื™ื™ื– ืึธื ืœื™ื™ืŸ ืงื•ืจืก "ืคืึทืš ื“ื–ืฉืึทื•ื•ืึท ื“ืขื•ื•ืขืœืึธืคึผืขืจ".

ื•ื•ื™ ืฆื• ืฉืคึผื™ืœืŸ ื–ื›ึผืจื•ืŸ ืงืึธืจื˜

ื“ืขืจ ืฉืคึผื™ืœ ื”ื™ื™ื‘ื˜ ื–ื™ืš ืืŸ ืžื™ื˜ ืึท ื“ืขืžืึทื ืกื˜ืจื™ื™ืฉืึทืŸ ืคื•ืŸ ืึท ื’ืึทื ื’ ืคื•ืŸ ืงืึทืจื“ืก. ื–ื™ื™ ืœื™ื’ืŸ ืคึผื ื™ื ืึทืจืึธืคึผ (ืจื™ืกืคึผืขืงื˜ื™ื•ื•ืœื™, ื‘ื™ืœื“ ืึทืจืึธืคึผ). ื•ื•ืขืŸ ืื™ืจ ื’ื™ื˜ ืื•ื™ืฃ ืื™ื™ื ืขืจ, ื“ื™ ื‘ื™ืœื“ ืึธืคึผืขื ืก ืคึฟืึทืจ ืึท ื‘ื™ืกืœ ืกืขืงื•ื ื“ืขืก.

ื“ื™ ืฉืคึผื™ืœืขืจ ืก ืึทืจื‘ืขื˜ ืื™ื– ืฆื• ื’ืขืคึฟื™ื ืขืŸ ืึทืœืข ืงืึทืจื“ืก ืžื™ื˜ ื“ื™ ื–ืขืœื‘ืข ื‘ื™ืœื“ืขืจ. ืื•ื™ื‘, ื ืึธืš ืขืคืŸ ื“ื™ ืขืจืฉื˜ืขืจ ืงืึธืจื˜, ืื™ืจ ืงืขืจ ืื™ื‘ืขืจ ื“ื™ ืจื’ืข ืื•ืŸ ื“ื™ ื‘ื™ืœื“ืขืจ ื’ืœื™ื™ึทื›ืŸ, ื‘ื™ื™ื“ืข ืงืึทืจื“ืก ื‘ืœื™ื™ื‘ืŸ ืึธืคืŸ. ืื•ื™ื‘ ื–ื™ื™ ื˜ืึธืŸ ื ื™ื˜ ื’ืœื™ื™ึทื›ืŸ, ื“ื™ ืงืึทืจื“ืก ื–ืขื ืขืŸ ืคืืจืžืื›ื˜ ื•ื•ื™ื“ืขืจ. ื“ืขืจ ืฆื™ืœ ืื™ื– ืฆื• ืขืคืขื ืขืŸ ืึทืœืฅ.

ืคึผืจื•ื™ืขืงื˜ ืกื˜ืจื•ืงื˜ื•ืจ

ืฆื• ืฉืึทืคึฟืŸ ืึท ืคึผืฉื•ื˜ ื•ื•ืขืจืกื™ืข ืคื•ืŸ โ€‹โ€‹โ€‹โ€‹ื“ืขื ืฉืคึผื™ืœ ืื™ืจ ื“ืึทืจืคึฟืŸ ื“ื™ ืคืืœื’ืขื ื“ืข ืงืึทืžืคึผืึธื•ื ืึทื ืฅ:

  • ืื™ื™ืŸ ืงืึธื ื˜ืจืึธืœืœืขืจ: GameController.swift.
  • ืื™ื™ืŸ ืžื™ื™ื ื•ื ื’: CardCell.swift.
  • ืฆื•ื•ื™ื™ ืžืึธื“ืขืœืก: MemoryGame.swift ืื•ืŸ Card.swift.
  • ืžืึทื™ื .ืกื˜ืึธืจื™ื‘ืึธืึทืจื“ ืฆื• ืขื ืฉื•ืจ ืึทื– ื“ื™ ื’ืื ืฆืข ื’ืึทื ื’ ืคื•ืŸ ืงืึทืžืคึผืึธื•ื ืึทื ืฅ ืื™ื– ื‘ื ื™ืžืฆื.

ืžื™ืจ ืึธื ื”ื™ื™ื‘ืŸ ืžื™ื˜ ื“ื™ ืกื™ืžืคึผืœืึทืกื˜ ืงืึธืžืคึผืึธื ืขื ื˜ ืคื•ืŸ ื“ื™ ืฉืคึผื™ืœ, ื“ื™ ืงืึทืจื“ืก.

ืงืึทืจื“.ืกื•ื•ื™ืคื˜

ื“ืขืจ ืงืึธืจื˜ ืžืึธื“ืขืœ ื•ื•ืขื˜ ื”ืึธื‘ืŸ ื“ืจื™ื™ ืคึผืจืึธืคึผืขืจื˜ื™ืขืก: ืฉื™ื™ึทืŸ ืฆื• ื™ื“ืขื ื˜ื™ืคื™ืฆื™ืจืŸ ื™ืขื“ืขืจ ืื™ื™ื ืขืจ, ืึท ื‘ื•ืœื™ืึทืŸ ื‘ื™ื™ึทื˜ืขื•ื•ื“ื™ืง ื’ืขื•ื•ื™ื–ืŸ ืฆื• ืกืคึผืขืฆื™ืคื™ืฆื™ืจืŸ ื“ื™ ืกื˜ืึทื˜ื•ืก ืคื•ืŸ ื“ื™ ืงืึธืจื˜ (ืคืึทืจื‘ืึธืจื’ืŸ ืึธื“ืขืจ ืึธืคึฟืŸ), ืื•ืŸ ืึทืจื˜ื•ื•ืึธืจืงURL ืคึฟืึทืจ ื“ื™ ื‘ื™ืœื“ืขืจ ืื•ื™ืฃ ื“ื™ ืงืึทืจื“ืก.

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    
}

ืื•ืŸ ืื™ื™ื ืขืจ ืžืขืจ ืื•ืคึฟืŸ ืื™ื– ื“ืืจืฃ ืฆื• ืฉืึทืจืŸ ื“ื™ ืงืึทืจื“ืก ืื™ืŸ ื“ื™ ืึธื ื”ื™ื™ื‘. ืžื™ืจ ื•ื•ืขืœืŸ ืžืึทื›ืŸ ืขืก ืึท ืคืึทืจืœืขื ื’ืขืจื•ื ื’ ืคื•ืŸ ื“ื™ Array ืงืœืึทืก.

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

ื’ื™ื™ ืืŸ.

ื“ื™ ืจื’ืข ืžืึธื“ืขืœ ืื™ื– MemoryGame, ื“ืึธ ืžื™ืจ ืฉื˜ืขืœืŸ ืึท 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    
}

ืื•ืคึฟืŸ ืคึฟืึทืจ ืงืจื™ื™ื™ื˜ื™ื ื’ ืึท ื ื™ื™ึท ืฉืคึผื™ืœ. ื“ืึธ ืžื™ืจ ืจื•ืคืŸ ื“ืขืจ ืขืจืฉื˜ืขืจ ืื•ืคึฟืŸ ืฆื• ืึธื ื”ื™ื™ื‘ืŸ ื“ื™ ืขืจืฉื˜ ืื•ื™ืกืœื™ื™ื’ ืื•ืŸ ื™ื ื™ืฉืึทืœื™ื™ื– ื“ื™ ืื™ื–ืคึผืœื™ื™ึทื™ื ื’ ื‘ื™ื™ึทื˜ืขื•ื•ื“ื™ืง ืฆื• ืืžืช.

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

ืื•ื™ื‘ ืžื™ืจ ื•ื•ื™ืœืŸ ืฆื• ืจื™ืกื˜ืึทืจื˜ ื“ื™ ืฉืคึผื™ืœ, ื“ืขืจื ืึธืš ืžื™ืจ ืฉื˜ืขืœืŸ ื“ื™ ืื™ื–ืคึผืœื™ื™ึทื™ื ื’ ื‘ื™ื™ึทื˜ืขื•ื•ื“ื™ืง ืฆื• ืคืึทืœืฉ ืื•ืŸ ื‘ืึทื–ื™ื™ึทื˜ื™ืงืŸ ื“ื™ ืขืจืฉื˜ ืื•ื™ืกืœื™ื™ื’ ืคื•ืŸ ื“ื™ ืงืึทืจื“ืก.

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 ืงื•ืงื˜ ืขืคึผืขืก ื•ื•ื™ ื“ืึธืก:

ืฉืจื™ื™ื‘ืŸ ืึท ื–ื›ึผืจื•ืŸ ืงืึทืจื“ืก ืฉืคึผื™ืœ ืื™ืŸ ืกื•ื•ื™ืคื˜

ื˜ื›ื™ืœืขืก, ืื™ืจ ื“ืึทืจืคึฟืŸ ืฆื• ืฉื˜ืขืœืŸ ื“ื™ ื ื™ื™ึทืข ืฉืคึผื™ืœ ื•ื•ื™ ViewDidLoad ืื™ืŸ ื“ื™ ืงืึธื ื˜ืจืึธืœืœืขืจ, ืึทืจื™ื™ึทื ื’ืขืจืขื›ื ื˜ ื“ื™ ื‘ื™ืœื“ืขืจ ืคึฟืึทืจ ื“ื™ ื’ืจื™ื“. ืื™ืŸ ื“ื™ ืฉืคึผื™ืœ, ืึทืœืข ื“ืขื ื•ื•ืขื˜ ื–ื™ื™ืŸ ืจืขืคึผืจื™ื–ืขื ื˜ื™ื“ ื“ื•ืจืš 4 * 4 ื–ืึทืžืœื•ื ื’ View. ืื•ื™ื‘ ืื™ืจ ื–ืขื ื˜ ื ืึธืš ื ื™ืฉื˜ ื‘ืึทืงืึทื ื˜ ืžื™ื˜ CollectionView, ื“ืึธ ืขืก ืื™ื– ืื™ืจ ืงืขื ืขืŸ ื‘ืึทืงื•ืžืขืŸ ื“ื™ ืื™ื ืคึฟืึธืจืžืึทืฆื™ืข ืื™ืจ ื“ืึทืจืคึฟืŸ.

ืžื™ืจ ื•ื•ืขืœืŸ ืงืึทื ืคื™ื’ื™ืขืจ ื“ื™ GameController ื•ื•ื™ ื“ืขืจ ื•ื•ืึธืจืฆืœ ืงืึธื ื˜ืจืึธืœืœืขืจ ืคื•ืŸ ื“ื™ ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ. ื“ื™ GameController ื•ื•ืขื˜ ื”ืึธื‘ืŸ ืึท ื–ืึทืžืœื•ื ื’ View ื•ื•ืึธืก ืžื™ืจ ื•ื•ืขืœืŸ ื“ืขืจืžืึธื ืขืŸ ื•ื•ื™ ืึทืŸ IBOoutlet. ืืŸ ืื ื“ืขืจ ืจืขืคึฟืขืจืขื ืฅ ืื™ื– ืฆื• ื“ื™ IBAction onStartGame () ืงื ืขืคึผืœ, ื“ืึธืก ืื™ื– ืึท UIButton, ืื™ืจ ืงืขื ืขืŸ ื–ืขืŸ ืขืก ืื™ืŸ ื“ื™ ืกื˜ืึธืจื™ื‘ืึธืึทืจื“ ื’ืขืจื•ืคึฟืŸ PLAY.

ื ื‘ื™ืกืœ ื•ื•ืขื’ืŸ ื“ื™ ื™ืžืคึผืœืึทืžืขื ื˜ื™ื™ืฉืึทืŸ ืคื•ืŸ ืงืึทื ื˜ืจืึธื•ืœืขืจื–:

  • ืขืจืฉื˜ืขืจ, ืžื™ืจ ื™ื ื™ืฉืึทืœื™ื™ื– ืฆื•ื•ื™ื™ ื”ื•ื™ืคึผื˜ ืึทื‘ื“ื–ืฉืขืงืฅ - ื“ื™ ื’ืจื™ื“: ืฉืคึผื™ืœ = ืžืขืžืึธืจื™ื’ืึทืžืข (), ืื•ืŸ ืึท ื’ืึทื ื’ ืคื•ืŸ ืงืึทืจื“ืก: ืงืึทืจื“ืก = [ืงืึทืจื“] ().
  • ืžื™ืจ ืฉื˜ืขืœืŸ ื“ื™ ืขืจืฉื˜ ื•ื•ืขืจื™ืึทื‘ืึทืœื– ื•ื•ื™ viewDidLoad, ื“ืึธืก ืื™ื– ื“ืขืจ ืขืจืฉื˜ืขืจ ืื•ืคึฟืŸ ื•ื•ืึธืก ืื™ื– ื’ืขืจื•ืคึฟืŸ ื‘ืฉืขืช ื“ื™ ืฉืคึผื™ืœ ืื™ื– ืคืœื™ืกื ื“ื™ืง.
  • collectionView ืื™ื– ื‘ืึทืฉื˜ื™ืžื˜ ืฆื• ืคืึทืจื‘ืึธืจื’ืŸ ื•ื•ื™ื™ึทืœ ืึทืœืข ืงืึทืจื“ืก ื–ืขื ืขืŸ ืคืึทืจื‘ืึธืจื’ืŸ ื‘ื™ื– ื“ืขืจ ื‘ืึทื ื™ืฆืขืจ ื“ืจื™ืงื˜ PLAY.
  • ื•ื•ื™ ื‘ืึทืœื“ ื•ื•ื™ ืžื™ืจ ื“ืจื™ืงืŸ PLAY, ื“ื™ onStartGame IBAction ืึธืคึผื˜ื™ื™ืœื•ื ื’ ืกื˜ืึทืจืฅ, ืื•ืŸ ืžื™ืจ ืฉื˜ืขืœืŸ ื“ื™ ื–ืึทืžืœื•ื ื’ View isHidden ืคืึทืจืžืึธื’ ืฆื• ืคืึทืœืฉ ืึทื–ื•ื™ ืึทื– ื“ื™ ืงืึทืจื“ืก ืงืขื ืขืŸ ื•ื•ืขืจืŸ ืงืขื ื˜ื™ืง.
  • ื™ืขื“ืขืจ ืžืึธืœ ื•ื•ืขืŸ ื“ืขืจ ื‘ืึทื ื™ืฆืขืจ ืกืึทืœืขืงืฅ ืึท ืงืึธืจื˜, ื“ื™ 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)
    }
}

ืœืึธืžื™ืจ ืื™ืฆื˜ ืึท ื‘ื™ืกืœ ืจืขื“ืŸ ื•ื•ืขื’ืŸ ื“ื™ ื•ื•ื™ื›ื˜ื™ืงืข ืคึผืจืึธื˜ืึธืงืึธืœืŸ.

ืคึผืจืึธื˜ืึธืงืึธืœืก

ืืจื‘ืขื˜ืŸ ืžื™ื˜ ืคึผืจืึธื˜ืึธืงืึธืœืก ืื™ื– ื“ื™ ื”ืึทืจืฅ ืคื•ืŸ ืกื•ื•ื™ืคื˜ ืคึผืจืึธื’ืจืึทืžืžื™ื ื’. ืคึผืจืึธื˜ืึธืงืึธืœืก ืฆื•ืฉื˜ืขืœืŸ ื“ื™ ืคื™ื™ื™ืงื™ื™ื˜ ืฆื• ื“ืขืคื™ื ื™ืจืŸ ื›ึผืœืœื™ื ืคึฟืึทืจ ืึท ืงืœืึทืก, ืกื˜ืจื•ืงื˜ื•ืจ ืึธื“ืขืจ ื™ื ื•ืžืขืจื™ื™ืฉืึทืŸ. ื“ืขื ืคึผืจื™ื ืฆื™ืคึผ ืึทืœืึทื•ื– ืื™ืจ ืฆื• ืฉืจื™ื™ึทื‘ืŸ ืžืึทื“ื–ืฉืึทืœืขืจ ืื•ืŸ ืขืงืกื˜ืขื ืกื™ื‘ืœืข ืงืึธื“. ืื™ืŸ ืคืึทืงื˜, ื“ืึธืก ืื™ื– ืึท ืžื•ืกื˜ืขืจ ื•ื•ืึธืก ืžื™ืจ ื–ืขื ืขืŸ ืฉื•ื™ืŸ ื™ืžืคึผืœืึทืžืขื ืึทื“ ืคึฟืึทืจ 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. ืขืจืฉื˜ืขืจ ืขืก ื•ื•ื™ื™ื–ื˜ ื“ื™ ืื•ื™ืกื’ืขืงืœื™ื‘ืŸ ืงืึธืจื˜. ื“ืึทืŸ ื˜ืฉืขืงืก ืฆื• ื–ืขืŸ ืื•ื™ื‘ ืขืก ืื™ื– ืึท ื’ืœื™ื™ึทื›ืŸ ืงืึธืจื˜ ืื™ืŸ ื“ื™ ืงืึทืจื“ืก ืฉืึธื•ื•ืŸ ืžืขื ื’ืข (ืื•ื™ื‘ ื“ื™ ื ื•ืžืขืจ ืคื•ืŸ ืงืึทืจื“ืก ืื™ื– ืžืึธื“ื ืข). ืื•ื™ื‘ ืขืก ืื™ื– ืื™ื™ืŸ, ื“ื™ ืื•ื™ืกื’ืขืงืœื™ื‘ืŸ ืงืึธืจื˜ ืื™ื– ืงืึทืžืคึผืขืจื“ ืžื™ื˜ ืื™ื. ืื•ื™ื‘ ื“ื™ ื‘ื™ืœื“ืขืจ ื–ืขื ืขืŸ ื“ื™ ื–ืขืœื‘ืข, ื‘ื™ื™ื“ืข ืงืึทืจื“ืก ื–ืขื ืขืŸ ืžื•ืกื™ืฃ ืฆื• ื“ื™ ืงืึทืจื“ืก ืื•ืŸ ื‘ืœื™ื™ื‘ืŸ ืžื™ื˜ ื“ื™ ืคึผื ื™ื ืึทืจื•ื™ืฃ. ืื•ื™ื‘ ืึทื ื“ืขืจืฉ, ื“ื™ ืงืึธืจื˜ ืœืึธื–ืŸ ื“ื™ ืงืึทืจื“ืก ื’ืขื•ื•ื™ื–ืŸ ืื•ืŸ ื‘ื™ื™ื“ืข ื–ืขื ืขืŸ ืื•ื™ืกื’ืขื“ืจื™ื™ื˜ ืžื™ื˜ ื“ื™ ืคึผื ื™ื ืึทืจืึธืคึผ.

memoryGameHideCards

ืื•ื™ื‘ ื“ื™ ืงืึทืจื“ืก ื˜ืึธืŸ ื ื™ื˜ ื’ืœื™ื™ึทื›ืŸ, ื“ืขื ืื•ืคึฟืŸ ืื™ื– ื’ืขืจื•ืคืŸ ืื•ืŸ ื“ื™ ืงืึธืจื˜ ื‘ื™ืœื“ืขืจ ื–ืขื ืขืŸ ืคืึทืจื‘ืึธืจื’ืŸ.

ื’ืขื•ื•ื™ื–ืŸ = ืคืึทืœืฉ.

memoryGameDidEnd

ื•ื•ืขืŸ ื“ืขื ืื•ืคึฟืŸ ืื™ื– ื’ืขืจื•ืคึฟืŸ, ืขืก ืžื™ื˜ืœ ืึทื– ืึทืœืข ืงืึทืจื“ืก ื–ืขื ืขืŸ ืฉื•ื™ืŸ ืื ื˜ืคืœืขืงื˜ ืื•ืŸ ื–ืขื ืขืŸ ืื™ืŸ ื“ื™ ืงืึทืจื“ืกShown ืจืฉื™ืžื”: cardsShown.count = cards.count, ืึทื–ื•ื™ ื“ืขืจ ืฉืคึผื™ืœ ืื™ื– ืื™ื‘ืขืจ. ื“ืขืจ ืื•ืคึฟืŸ ืื™ื– ื’ืขืจื•ืคึฟืŸ ืกืคึผืึทืกื™ืคื™ืงืœื™ ื ืึธืš ืžื™ืจ ื”ืึธื‘ืŸ ื’ืขืจื•ืคืŸ endGame () ืฆื• ืฉื˜ืขืœืŸ ื“ื™ isPlaying var ืฆื• ืคืึทืœืฉ, ื ืึธืš ื•ื•ืึธืก ื“ื™ ืฉืคึผื™ืœ ืกื•ืฃ ืึธื ื–ืึธื’ ืื™ื– ื’ืขื•ื•ื™ื–ืŸ. ืื•ื™ืš ืึทืœืขืจื˜ืงืึธื ื˜ืจืึธืœืœืขืจ ืื™ื– ื’ืขื ื™ืฆื˜ ื•ื•ื™ ืึท ื’ืจืื“ืŸ ืคึฟืึทืจ ื“ื™ ืงืึธื ื˜ืจืึธืœืœืขืจ. 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()
    }
}

ืฉืจื™ื™ื‘ืŸ ืึท ื–ื›ึผืจื•ืŸ ืงืึทืจื“ืก ืฉืคึผื™ืœ ืื™ืŸ ืกื•ื•ื™ืคื˜
ืึทืงื˜ื•ืึทืœืœื™, ืึทื– ืก ืึทืœืข. ืื™ืจ ืงืขื ืขืŸ ื ื•ืฆืŸ ื“ืขื ืคึผืจื•ื™ืขืงื˜ ืฆื• ืฉืึทืคึฟืŸ ื“ื™ื™ืŸ ืื™ื™ื’ืขื ืข ื•ื•ืขืจืกื™ืข ืคื•ืŸ โ€‹โ€‹โ€‹โ€‹ื“ื™ ืฉืคึผื™ืœ.

ื’ืœื™ืงืœืขืš ืงืึธื“ื™ืจื•ื ื’!

Skillbox ืจืขืงืึทืžืขื ื“ื–:

ืžืงื•ืจ: www.habr.com

ืœื™ื™ื’ืŸ ืึท ื‘ืึทืžืขืจืงื•ื ื’