Atminties kortelių žaidimo rašymas naudojant „Swift“.

Atminties kortelių žaidimo rašymas naudojant „Swift“.

Šiame straipsnyje aprašomas paprasto atminties lavinimo žaidimo, kuris man labai patinka, kūrimo procesas. Be to, kad jis pats savaime yra geras, jūs išmoksite šiek tiek daugiau apie „Swift“ klases ir protokolus. Tačiau prieš pradėdami supraskime patį žaidimą.

Primename: visiems „Habr“ skaitytojams – 10 000 rublių nuolaida užsiregistravus į bet kurį „Skillbox“ kursą naudojant „Habr“ reklamos kodą.

„Skillbox“ rekomenduoja: Mokomasis internetinis kursas „Java kūrėjo profesija“.

Kaip žaisti atminties kortelę

Žaidimas prasideda kortelių rinkinio demonstravimu. Jie guli veidu žemyn (atitinkamai, vaizdas žemyn). Spustelėjus bet kurį, vaizdas atsidaro kelioms sekundėms.

Žaidėjo užduotis – surasti visas kortas su tais pačiais paveikslėliais. Jei atidarę pirmąją kortelę apverčiate antrąją ir nuotraukos sutampa, abi kortelės lieka atviros. Jei jie nesutampa, kortelės vėl uždaromos. Tikslas – viską atverti.

Projekto struktūra

Norėdami sukurti paprastą šio žaidimo versiją, jums reikia šių komponentų:

  • Vienas valdiklis: GameController.swift.
  • Vienas vaizdas: CardCell.swift.
  • Du modeliai: MemoryGame.swift ir Card.swift.
  • Main.storyboard, kad būtų užtikrintas visas komponentų rinkinys.

Pradedame nuo paprasčiausio žaidimo komponento – kortelių.

Card.swift

Kortelės modelis turės tris ypatybes: ID kiekvienai iš jų identifikuoti, loginį kintamąjį, rodantį kortelės būseną (paslėptą arba atidarytą), ir artworkURL kortelėse esantiems vaizdams.

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

Taip pat reikės šių metodų, kad galėtumėte valdyti naudotojo sąveiką su žemėlapiais:

Vaizdo atvaizdavimo kortelėje metodas. Čia iš naujo nustatome visas ypatybes į numatytuosius. ID sugeneruojame atsitiktinį ID, iškviesdami NSUUIS().uuidString.

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

Tapatybės kortelių palyginimo metodas.

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

Kiekvienos kortelės kopijos kūrimo būdas - norint gauti didesnį skaičių identiškų. Šis metodas grąžins kortelę su panašiomis vertėmis.

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

Ir reikia dar vieno metodo, norint pradžioje sumaišyti kortas. Padarysime tai „Array“ klasės plėtiniu.

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

Ir čia yra Kortelės modelio kodo įgyvendinimas su visomis savybėmis ir metodais.

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

Pirmyn.

Antrasis modelis yra „MemoryGame“, čia nustatome 4*4 tinklelį. Modelis turės tokias ypatybes kaip kortelės (kortelių masyvas tinklelyje), masyvas cardsShown su jau atidarytomis kortelėmis ir loginis kintamasis isPlaying, kad būtų galima stebėti žaidimo būseną.

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

Taip pat turime sukurti metodus, kaip kontroliuoti vartotojų sąveiką su tinklu.

Metodas, kuris maišo kortas tinklelyje.

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

Naujo žaidimo kūrimo būdas. Čia mes vadiname pirmąjį metodą pradėti pradinį išdėstymą ir inicijuoti isPlaying kintamąjį į true.

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

Jei norime iš naujo paleisti žaidimą, tada kintamąjį isPlaying nustatome į false ir pašaliname pradinį kortelių išdėstymą.

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

Paspaustų kortelių tikrinimo metodas. Daugiau apie jį vėliau.

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

Metodas, grąžinantis konkrečios kortelės padėtį.

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

Pasirinktos kortelės atitikties standartui tikrinimas.

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

Šis metodas nuskaito paskutinį **cardsShown** masyvo elementą ir grąžina neatitinkančią kortelę.

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

Main.soryboard atrodo maždaug taip:

Atminties kortelių žaidimo rašymas naudojant „Swift“.

Iš pradžių turite nustatyti naują žaidimą kaip viewDidLoad valdiklyje, įskaitant tinklelio vaizdus. Žaidime visa tai pavaizduos 4*4 kolekcijaView. Jei dar nesate susipažinę su collectionView, čia jis yra galite gauti reikiamą informaciją.

„GameController“ sukonfigūruosime kaip programos šakninį valdiklį. GameController turės kolekcijąView, kurią vadinsime IBOoutlet. Kita nuoroda yra į IBAction onStartGame() mygtuką, tai yra UIButton, jį galite pamatyti siužete pavadinimu PLAY.

Šiek tiek apie valdiklių diegimą:

  • Pirmiausia inicijuojame du pagrindinius objektus – tinklelį: žaidimas = MemoryGame() ir kortelių rinkinį: cards = [Card]().
  • Pradinius kintamuosius nustatome kaip viewDidLoad, tai yra pirmasis metodas, kuris iškviečiamas žaidimui veikiant.
  • collectionView nustatytas kaip paslėptas, nes visos kortelės yra paslėptos, kol vartotojas nepaspaus PLAY.
  • Kai tik paspaudžiame PLAY, prasidės onStartGame IBAction skyrius, o ypatybę collectionView isHidden nustatome į false, kad kortelės būtų matomos.
  • Kiekvieną kartą, kai vartotojas pasirenka kortelę, iškviečiamas didSelectItemAt metodas. Metodą mes vadiname didSelectCard, kad įgyvendintume pagrindinę žaidimo logiką.

Štai galutinis GameController įgyvendinimas:

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

Dabar pakalbėkime apie svarbius protokolus.

Protokolai

Darbas su protokolais yra „Swift“ programavimo pagrindas. Protokolai suteikia galimybę apibrėžti klasės, struktūros ar sąrašo taisykles. Šis principas leidžia rašyti modulinį ir išplečiamą kodą. Tiesą sakant, tai yra modelis, kurį jau įgyvendiname kolekcijai „GameController“. Dabar sukurkime savo versiją. Sintaksė atrodys taip:

protocol MemoryGameProtocol {
    //protocol definition goes here
}

Žinome, kad protokolas leidžia apibrėžti klasės įgyvendinimo taisykles ar instrukcijas, todėl pagalvokime, kokios jos turėtų būti. Iš viso reikia keturių.

  • Žaidimo pradžia: memoryGameDidStart.
  • Kortelę reikia apversti puse žemyn: memoryGameShowCards.
  • Kortelę reikia apversti puse žemyn: memoryGameHideCards.
  • Žaidimo pabaiga: memoryGameDidEnd.

Visi keturi metodai gali būti įdiegti pagrindinei klasei, kuri yra „GameController“.

memoryGameDidStart

Paleidus šį metodą, žaidimas turėtų prasidėti (vartotojas paspaudžia PLAY). Čia tiesiog iš naujo įkelsime turinį iškviesdami collectionView.reloadData(), kuri sumaišys korteles.

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

„MemoryGameShowCards“.

Šį metodą vadiname iš kolekcijaSDViewSelectItemAt. Pirmiausia rodoma pasirinkta kortelė. Tada patikrina, ar masyve cardsShown nėra nesuderinamos kortelės (jei rodomų kortelių skaičius yra nelyginis). Jei yra, pasirinkta kortelė lyginama su ja. Jei nuotraukos yra vienodos, abi kortelės pridedamos prie kortelių Rodomos ir lieka užvertos. Jei skiriasi, kortelė palieka rodomas korteles ir abi yra apverstos.

„MemoryGameHideCards“.

Jei kortelės nesutampa, iškviečiamas šis metodas ir kortelių vaizdai paslepiami.

parodyta = klaidinga.

memoryGameDidEnd

Kai iškviečiamas šis metodas, tai reiškia, kad visos kortos jau yra atskleistos ir yra sąraše cardsShown: cardsShown.count = cards.count, taigi žaidimas baigtas. Metodas iškviečiamas konkrečiai po to, kai iškviečiame endGame(), norėdami nustatyti isPlaying var į false, po kurio rodomas žaidimo pabaigos pranešimas. Taip pat alertController naudojamas kaip valdiklio indikatorius. Iškviečiamas viewDidDisappar ir žaidimas iš naujo nustatomas.

Štai kaip viskas atrodo „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()
    }
}

Atminties kortelių žaidimo rašymas naudojant „Swift“.
Tiesą sakant, tai viskas. Naudodami šį projektą galite sukurti savo žaidimo versiją.

Laimingas kodavimas!

„Skillbox“ rekomenduoja:

Šaltinis: www.habr.com

Добавить комментарий