Kitba ta' Logħba tal-Kards tal-Memorja f'Swift

Kitba ta' Logħba tal-Kards tal-Memorja f'Swift

Dan l-artikolu jiddeskrivi l-proċess tal-ħolqien ta 'logħba sempliċi ta' taħriġ tal-memorja li nħobb ħafna. Minbarra li tkun tajba fiha nnifisha, titgħallem ftit aktar dwar il-klassijiet u l-protokolli Swift kif tmur. Iżda qabel ma nibdew, ejja nifhmu l-logħba nnifisha.

Infakkrukom: għall-qarrejja kollha ta '"Habr" - skont ta' 10 rublu meta tirreġistra fi kwalunkwe kors ta 'Skillbox billi tuża l-kodiċi promozzjonali "Habr".

Skillbox jirrakkomanda: Kors edukattiv onlajn "Professjoni Java Developer".

Kif tilgħab Memory Card

Il-logħba tibda b'dimostrazzjoni ta' sett ta' karti. Huma jimteddu wiċċ 'l isfel (rispettivament, immaġni 'l isfel). Meta tikklikkja fuq kwalunkwe waħda, l-immaġni tiftaħ għal ftit sekondi.

Il-kompitu tal-plejer huwa li jsib il-karti kollha bl-istess stampi. Jekk, wara li tiftaħ l-ewwel karta, taqleb it-tieni u l-istampi jaqblu, iż-żewġ karti jibqgħu miftuħa. Jekk ma jaqblux, il-karti jerġgħu jingħalqu. L-għan huwa li tiftaħ kollox.

Struttura tal-proġett

Biex toħloq verżjoni sempliċi ta 'din il-logħba għandek bżonn il-komponenti li ġejjin:

  • Kontrollur wieħed: GameController.swift.
  • One View: CardCell.swift.
  • Żewġ Mudelli: MemoryGame.swift u Card.swift.
  • Main.storyboard biex jiġi żgurat li s-sett kollu ta 'komponenti huwa disponibbli.

Nibdew bl-aktar komponent sempliċi tal-logħba, il-karti.

Card.swift

Il-mudell tal-karta se jkollu tliet proprjetajiet: id biex tidentifika kull waħda, varjabbli boolean murija biex tispeċifika l-istatus tal-karta (moħbija jew miftuħa), u artworkURL għall-immaġini fuq il-karti.

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

Ikollok bżonn ukoll dawn il-metodi biex tikkontrolla l-interazzjoni tal-utent mal-mapep:

Metodu għall-wiri ta 'immaġni fuq karta. Hawnhekk irrisettjaw il-proprjetajiet kollha għal default. Għall-id, niġġeneraw id każwali billi nsejħu NSUUIS().uuidString.

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

Metodu għat-tqabbil tal-karti tal-identità.

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

Metodu biex tinħoloq kopja ta' kull karta - sabiex tikseb numru akbar ta 'dawk identiċi. Dan il-metodu se jirritorna karta b'valuri simili.

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

U metodu ieħor huwa meħtieġ biex tħawwad il-karti fil-bidu. Aħna ser nagħmluha estensjoni tal-klassi Array.

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

U hawn hija l-implimentazzjoni tal-kodiċi għall-mudell tal-Kard bil-proprjetajiet u l-metodi kollha.

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

Jimxi 'l quddiem.

It-tieni mudell huwa MemoryGame, hawn waqqafna grilja 4 * 4. Il-mudell se jkollu proprjetajiet bħal karti (firxa ta 'karti fuq grilja), firxa ta' kardsShown b'karti diġà miftuħa, u varjabbli boolean qed Playing biex issegwi l-istatus tal-logħba.

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

Għandna bżonn ukoll li niżviluppaw metodi biex nikkontrollaw l-interazzjoni tal-utent mal-grid.

Metodu li jgħaqqad il-karti fi grid.

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

Metodu għall-ħolqien ta 'logħba ġdida. Hawnhekk insejħu l-ewwel metodu biex tibda t-tqassim inizjali u inizjalizza l-varjabbli isPlaying għal vera.

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

Jekk irridu nibdew mill-ġdid il-logħba, imbagħad issettja l-varjabbli isPlaying għal falza u neħħi t-tqassim inizjali tal-karti.

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

Metodu għall-verifika tal-kards ikklikkjati. Aktar dwaru aktar tard.

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

Metodu li jirritorna l-pożizzjoni ta 'karta speċifika.

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

Iċċekkjar tal-konformità tal-karta magħżula mal-istandard.

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

Dan il-metodu jaqra l-aħħar element fil-firxa **cardsShown** u jirritorna l-karta li ma taqbilx.

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 u GameController.swift

Main.storyboard jidher xi ħaġa bħal din:

Kitba ta' Logħba tal-Kards tal-Memorja f'Swift

Inizjalment, għandek bżonn issettja l-logħba l-ġdida bħala viewDidLoad fil-kontrollur, inklużi l-immaġini għall-grilja. Fil-logħba, dan kollu se jkun rappreżentat minn 4 * 4 collectionView. Jekk għadek m'intix familjari ma' collectionView, hawnhekk qiegħed tista' tikseb l-informazzjoni li għandek bżonn.

Aħna ser tikkonfigura l-GameController bħala l-kontrollur tal-għeruq tal-applikazzjoni. Il-GameController se jkollu collectionView li se nirreferuha bħala IBOutlet. Referenza oħra hija għall-buttuna IBAction onStartGame(), din hija UIButton, tista 'taraha fl-istoryboard imsejjaħ PLAY.

Ftit dwar l-implimentazzjoni tal-kontrolluri:

  • L-ewwel, aħna initialize żewġ oġġetti ewlenin - il-grid: logħba = MemoryGame (), u sett ta 'karti: karti = [Kard] ().
  • Aħna waqqafna l-varjabbli inizjali bħala viewDidLoad, dan huwa l-ewwel metodu li jissejjaħ waqt li l-logħba tkun qed taħdem.
  • collectionView huwa ssettjat biex moħbi għaliex il-karti kollha huma moħbija sakemm l-utent jagħfas PLAY.
  • Hekk kif nagħfsu PLAY, tibda s-sezzjoni onStartGame IBAction, u nissettjaw il-proprjetà collectionView isHidden għal falza sabiex il-karti jkunu jistgħu jsiru viżibbli.
  • Kull darba li l-utent jagħżel karta, jissejjaħ il-metodu didSelectItemAt. Fil-metodu li nsejħu didSelectCard biex timplimenta l-loġika tal-logħba prinċipali.

Hawnhekk hawn l-implimentazzjoni finali tal-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)
    }
}

Issa ejja nitkellmu ftit dwar il-protokolli importanti.

Protokolli

Il-ħidma bi protokolli hija l-qalba tal-ipprogrammar Swift. Protokolli jipprovdu l-abbiltà li jiddefinixxu regoli għal klassi, struttura, jew enumerazzjoni. Dan il-prinċipju jippermettilek tikteb kodiċi modulari u estensibbli. Fil-fatt, dan huwa mudell li diġà qed nimplimentaw għal collectionView fil-GameController. Issa ejja nagħmlu l-verżjoni tagħna stess. Is-sintassi se tidher bħal din:

protocol MemoryGameProtocol {
    //protocol definition goes here
}

Aħna nafu li protokoll jippermettilna niddefinixxu regoli jew struzzjonijiet għall-implimentazzjoni ta 'klassi, allura ejja naħsbu dwar x'għandhom ikunu. Għandek bżonn erbgħa b'kollox.

  • Bidu tal-logħba: memoryGameDidStart.
  • Trid iddawwar il-karta wiċċ l-isfel: memoryGameShowCards.
  • Trid iddawwar il-karta wiċċ l-isfel: memoryGameHideCards.
  • Tmiem tal-logħba: memoryGameDidEnd.

L-erba 'metodi kollha jistgħu jiġu implimentati għall-klassi prinċipali, li hija GameController.

memoryGameDidStart

Meta dan il-metodu jitmexxa, il-logħba għandha tibda (l-utent jagħfas PLAY). Hawnhekk aħna sempliċiment nerġgħu ngħaġġu l-kontenut billi nsejħu collectionView.reloadData(), li se shuffle l-karti.

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

MemoryGameShowCards

Aħna nsejħu dan il-metodu minn collectionSDViewSelectItemAt. L-ewwel turi l-karta magħżula. Imbagħad jiċċekkja biex tara jekk hemmx karta mhux imqabbla fil-firxa cardsShown (jekk in-numru ta 'cardsShown huwiex fard). Jekk hemm waħda, il-karta magħżula titqabbel magħha. Jekk l-istampi huma l-istess, iż-żewġ karti jiżdiedu mal-karti murija u jibqgħu wiċċhom 'il fuq. Jekk differenti, il-karta tħalli l-karti murija u t-tnejn jinqalbu wiċċhom 'l isfel.

memoryGameHideCards

Jekk il-karti ma jaqblux, dan il-metodu jissejjaħ u l-immaġini tal-karti huma moħbija.

muri = falz.

memoryGameDidEnd

Meta jissejjaħ dan il-metodu, dan ifisser li l-karti kollha huma diġà żvelati u jinsabu fil-lista tal-kartiShown: cardsShown.count = cards.count, għalhekk il-logħba spiċċat. Il-metodu jissejjaħ speċifikament wara li sejjaħna endGame() biex tissettja l-isPlaying var għal falza, u wara jintwera l-messaġġ tat-tmiem tal-logħba. Ukoll alertController jintuża bħala indikatur għall-kontrollur. viewDidDisappear tissejjaħ u l-logħba hija reset.

Hawn kif jidher kollu f'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()
    }
}

Kitba ta' Logħba tal-Kards tal-Memorja f'Swift
Fil-fatt, dak kollu. Tista 'tuża dan il-proġett biex toħloq il-verżjoni tiegħek tal-logħba.

Kodifikazzjoni kuntenti!

Skillbox jirrakkomanda:

Sors: www.habr.com

Żid kumment