Kuandika Mchezo wa Kadi za Kumbukumbu katika Swift

Kuandika Mchezo wa Kadi za Kumbukumbu katika Swift

Nakala hii inaelezea mchakato wa kuunda mchezo rahisi wa mafunzo ya kumbukumbu ambao ninaupenda sana. Kando na kuwa mzuri yenyewe, utajifunza zaidi kuhusu madarasa na itifaki za Swift unapoendelea. Lakini kabla ya kuanza, hebu tuelewe mchezo wenyewe.

Tunakukumbusha: kwa wasomaji wote wa "Habr" - punguzo la rubles 10 wakati wa kujiandikisha katika kozi yoyote ya Skillbox kwa kutumia msimbo wa uendelezaji wa "Habr".

Skillbox inapendekeza: Kozi ya elimu mtandaoni "Msanidi programu wa Java".

Jinsi ya kucheza Kumbukumbu Kadi

Mchezo huanza na onyesho la seti ya kadi. Wanalala chini (kwa mtiririko huo, picha chini). Unapobofya yoyote, picha inafungua kwa sekunde chache.

Kazi ya mchezaji ni kupata kadi zote zilizo na picha sawa. Ikiwa, baada ya kufungua kadi ya kwanza, unageuka ya pili na picha zinafanana, kadi zote mbili zinabaki wazi. Ikiwa hazifanani, kadi zimefungwa tena. Lengo ni kufungua kila kitu.

Muundo wa mradi

Ili kuunda toleo rahisi la mchezo huu unahitaji vifaa vifuatavyo:

  • Kidhibiti kimoja: GameController.swift.
  • Mtazamo Mmoja: CardCell.swift.
  • Miundo miwili: MemoryGame.swift na Card.swift.
  • Main.storyboard ili kuhakikisha kuwa seti nzima ya vipengele inapatikana.

Tunaanza na sehemu rahisi zaidi ya mchezo, kadi.

Kadi.mwepesi

Muundo wa kadi utakuwa na sifa tatu: kitambulisho cha kutambua kila moja, kigezo cha boolean kinachoonyeshwa ili kubainisha hali ya kadi (iliyofichwa au iliyofunguliwa), na URL ya mchoro kwa picha zilizo kwenye kadi.

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

Utahitaji pia njia hizi ili kudhibiti mwingiliano wa watumiaji na ramani:

Njia ya kuonyesha picha kwenye kadi. Hapa tunaweka upya mali zote kuwa chaguo-msingi. Kwa kitambulisho, tunatoa kitambulisho nasibu kwa kupiga simu NSUUIS().uuidString.

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

Njia ya kulinganisha vitambulisho.

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

Njia ya kuunda nakala ya kila kadi - ili kupata idadi kubwa ya zile zinazofanana. Njia hii itarudisha kadi iliyo na maadili sawa.

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

Na njia moja zaidi inahitajika ili kuchanganya kadi mwanzoni. Tutafanya ugani wa darasa la Array.

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

Na hapa ni utekelezaji wa kanuni kwa mfano wa Kadi na mali na mbinu zote.

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

Endelea.

Mfano wa pili ni MemoryGame, hapa tunaweka gridi ya 4 * 4. Muundo huo utakuwa na sifa kama vile kadi (safu ya kadi kwenye gridi ya taifa), safu ya kadi zinazoonyeshwa na kadi tayari zimefunguliwa, na kigezo cha boolean kinacheza ili kufuatilia hali ya mchezo.

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

Tunahitaji pia kuunda mbinu za kudhibiti mwingiliano wa watumiaji na gridi ya taifa.

Njia ambayo huchanganya kadi kwenye gridi ya taifa.

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

Njia ya kuunda mchezo mpya. Hapa tunaita njia ya kwanza kuanza mpangilio wa awali na kuanzisha utofauti wa isPlaying kuwa kweli.

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

Ikiwa tunataka kuanza tena mchezo, kisha tunaweka tofauti ya isPlaying kuwa uongo na kuondoa mpangilio wa awali wa kadi.

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

Mbinu ya kuthibitisha kadi zilizobofya. Zaidi kuhusu yeye baadaye.

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

Njia ambayo inarudisha nafasi ya kadi maalum.

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

Kuangalia kufuata kwa kadi iliyochaguliwa na kiwango.

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

Mbinu hii husoma kipengele cha mwisho katika safu ya **kadiZilizoonyeshwa** na kurejesha kadi isiyolingana.

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

Ubao.kuu wa hadithi na GameController.mwepesi

Main.storyboard inaonekana kitu kama hiki:

Kuandika Mchezo wa Kadi za Kumbukumbu katika Swift

Hapo awali, unahitaji kuweka mchezo mpya kama viewDidLoad katika kidhibiti, ikijumuisha picha za gridi ya taifa. Katika mchezo, yote haya yatawakilishwa na 4*4 collectionView. Ikiwa bado haujafahamu collectionView, hii hapa unaweza kupata habari unayohitaji.

Tutasanidi GameController kama kidhibiti kikuu cha programu. GameController itakuwa na collectionView ambayo tutarejelea kama IBOutlet. Rejea nyingine ni kitufe cha IBAction onStartGame(), hii ni UIButton, unaweza kuiona kwenye ubao wa hadithi inayoitwa PLAY.

Kidogo juu ya utekelezaji wa vidhibiti:

  • Kwanza, tunaanzisha vitu viwili kuu - gridi ya taifa: mchezo = MemoryGame (), na seti ya kadi: kadi = [Kadi] ().
  • Tunaweka vigezo vya awali kama viewDidLoad, hii ndiyo njia ya kwanza inayoitwa wakati mchezo unaendelea.
  • collectionView imewekwa kufichwa kwa sababu kadi zote zimefichwa hadi mtumiaji abonyeze PLAY.
  • Mara tu tunapobonyeza PLAY, sehemu ya onStartGame IBAction huanza, na tunaweka collectionView isHidden mali kuwa sivyo ili kadi ziweze kuonekana.
  • Kila wakati mtumiaji anachagua kadi, mbinu ya didSelectItemAt inaitwa. Katika njia tunayoita didSelectCard kutekeleza mantiki kuu ya mchezo.

Huu hapa ni utekelezaji wa mwisho wa 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)
    }
}

Sasa hebu tuzungumze kidogo kuhusu itifaki muhimu.

Itifaki

Kufanya kazi na itifaki ndio msingi wa programu ya Swift. Itifaki hutoa uwezo wa kufafanua sheria za darasa, muundo au hesabu. Kanuni hii hukuruhusu kuandika msimbo wa kawaida na wa kupanuka. Kwa kweli, huu ni muundo ambao tayari tunatekeleza kwa mkusanyikoTazama katika GameController. Sasa hebu tufanye toleo letu wenyewe. Syntax itaonekana kama hii:

protocol MemoryGameProtocol {
    //protocol definition goes here
}

Tunajua kuwa itifaki huturuhusu kufafanua sheria au maagizo ya utekelezaji wa darasa, kwa hivyo hebu tufikirie jinsi zinafaa kuwa. Unahitaji nne kwa jumla.

  • Mwanzo wa mchezo: memoryGameDidStart.
  • Unahitaji kugeuza kadi uso chini: memoryGameShowCards.
  • Unahitaji kugeuza kadi uso chini: memoryGameHideCards.
  • Mwisho wa mchezo: memoryGameDidEnd.

Njia zote nne zinaweza kutekelezwa kwa darasa kuu, ambalo ni GameController.

memoryGameDidStart

Wakati njia hii inaendeshwa, mchezo unapaswa kuanza (mtumiaji bonyeza PLAY). Hapa tutapakia upya maudhui kwa kupiga simu collectionView.reloadData(), ambayo itachanganya kadi.

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

memoryGameShowCards

Tunaita njia hii kutoka kwa collectionSDViewSelectItemAt. Kwanza inaonyesha kadi iliyochaguliwa. Kisha angalia ili kuona kama kuna kadi isiyolinganishwa katika safu ya kadiInayoonyeshwa (ikiwa idadi ya kadiIliyoonyeshwa ni isiyo ya kawaida). Ikiwa kuna moja, kadi iliyochaguliwa inalinganishwa nayo. Ikiwa picha ni sawa, kadi zote mbili huongezwa kwenye kadi Zilizoonyeshwa na kubaki zimetazamana. Ikiwa ni tofauti, kadi huacha kadi Imeonyeshwa na zote mbili zimegeuzwa kifudifudi.

kumbukumbuMchezoFichaKadi

Ikiwa kadi hazifanani, njia hii inaitwa na picha za kadi zimefichwa.

imeonyeshwa = uongo.

memoryGameDidEnd

Njia hii inapoitwa, inamaanisha kuwa kadi zote tayari zimefichuliwa na ziko kwenye orodha ya kadi zilizoonyeshwa: cardsShown.count = cards.count, hivyo mchezo umeisha. Njia hiyo inaitwa mahususi baada ya sisi kuita endGame() kuweka isPlaying var kuwa sivyo, kisha ujumbe wa mwisho wa mchezo utaonyeshwa. Pia alertController inatumika kama kiashirio cha kidhibiti. viewDidDispear inaitwa na mchezo umewekwa upya.

Hivi ndivyo inavyoonekana katika 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()
    }
}

Kuandika Mchezo wa Kadi za Kumbukumbu katika Swift
Kweli, hiyo ndiyo yote. Unaweza kutumia mradi huu kuunda toleo lako la mchezo.

Furahia kuweka msimbo!

Skillbox inapendekeza:

Chanzo: mapenzi.com

Kuongeza maoni