Pagsulat sa Dula sa Memory Card sa Swift

Pagsulat sa Dula sa Memory Card sa Swift

Gihubit niini nga artikulo ang proseso sa paghimo og usa ka yano nga dula sa pagbansay sa memorya nga gusto nako. Gawas nga maayo sa iyang kaugalingon, makakat-on ka pa bahin sa mga klase sa Swift ug mga protocol samtang naglakaw ka. Apan sa dili pa kita magsugod, atong sabton ang dula mismo.

Gipahinumduman namon ikaw: alang sa tanan nga mga magbabasa sa "Habr" - usa ka diskwento sa 10 nga mga rubles kung nagpalista sa bisan unsang kurso sa Skillbox gamit ang code sa promosyon nga "Habr".

Girekomenda sa Skillbox: Online nga kurso sa edukasyon "Propesyon nga Java Developer".

Giunsa ang pagdula sa Memory Card

Ang dula magsugod sa usa ka demonstrasyon sa usa ka set sa mga kard. Sila mohigda nga nag-atubang (sa matag usa, hulagway sa ubos). Kung mag-klik ka sa bisan kinsa, ang imahe magbukas sa pipila ka segundo.

Ang tahas sa magdudula mao ang pagpangita sa tanan nga mga kard nga adunay parehas nga mga litrato. Kung, pagkahuman sa pag-abli sa una nga kard, imong ibalik ang ikaduha ug ang mga litrato magtugma, ang duha nga mga kard magpabilin nga bukas. Kung dili sila magkatugma, ang mga kard sirado pag-usab. Ang tumong mao ang pag-abli sa tanan.

Istruktura sa proyekto

Aron makahimo usa ka yano nga bersyon sa kini nga dula kinahanglan nimo ang mga musunud nga sangkap:

  • Usa ka Controller: GameController.swift.
  • Usa ka Pagtan-aw: CardCell.swift.
  • Duha ka Modelo: MemoryGame.swift ug Card.swift.
  • Main.storyboard aron masiguro nga ang tibuuk nga set sa mga sangkap magamit.

Nagsugod kami sa pinakasimple nga bahin sa dula, ang mga kard.

Card.swift

Ang modelo sa kard adunay tulo ka mga kabtangan: id aron mailhan ang matag usa, usa ka boolean nga variable nga gipakita aron mahibal-an ang kahimtang sa kard (gitago o bukas), ug artworkURL alang sa mga imahe sa mga kard.

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

Kinahanglan usab nimo kini nga mga pamaagi aron makontrol ang interaksyon sa tiggamit sa mga mapa:

Pamaagi sa pagpakita sa usa ka imahe sa usa ka kard. Dinhi among gi-reset ang tanan nga mga kabtangan sa default. Para sa id, makamugna mi og random id pinaagi sa pagtawag sa NSUUIS().uuidString.

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

Pamaagi sa pagtandi sa mga ID card.

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

Pamaagi sa paghimo og kopya sa matag kard - aron makakuha og mas daghang ihap sa parehas. Kini nga pamaagi ibalik ang kard nga adunay parehas nga kantidad.

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

Ug usa pa nga pamaagi ang gikinahanglan aron i-shuffle ang mga kard sa pagsugod. Himoon nato kini nga extension sa klase sa Array.

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

Ug ania ang pagpatuman sa code alang sa modelo sa Card nga adunay tanan nga mga kabtangan ug pamaagi.

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

Padayon.

Ang ikaduha nga modelo mao ang MemoryGame, dinhi nagbutang kami og 4 * 4 grid. Ang modelo adunay mga kabtangan sama sa mga kard (usa ka han-ay sa mga kard sa usa ka grid), usa ka kardGipakita nga laray nga adunay mga kard nga bukas na, ug usa ka boolean nga variable nga nagdula aron masubay ang kahimtang sa dula.

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

Kinahanglan usab namon nga maghimo mga pamaagi aron makontrol ang interaksyon sa tiggamit sa grid.

Usa ka pamaagi nga nag-shuffle sa mga kard sa usa ka grid.

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

Pamaagi sa paghimo og bag-ong dula. Dinhi among gitawag ang unang pamaagi aron masugdan ang inisyal nga layout ug i-initialize ang isPlaying variable ngadto sa true.

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

Kung gusto namon nga i-restart ang dula, unya among gibutang ang isPlaying variable sa bakak ug tangtangon ang inisyal nga layout sa mga kard.

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

Pamaagi sa pag-verify sa gi-klik nga mga kard. Dugang pa bahin kaniya sa ulahi.

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

Usa ka pamaagi nga nagbalik sa posisyon sa usa ka piho nga kard.

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

Pagsusi sa pagsunod sa pinili nga kard sa sumbanan.

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

Kini nga pamaagi magbasa sa kataposang elemento sa **cardsShown** array ug ibalik ang non-matching card.

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

Ang Main.storyboard ingon niini:

Pagsulat sa Dula sa Memory Card sa Swift

Sa sinugdan, kinahanglan nimo nga itakda ang bag-ong dula ingon viewDidLoad sa controller, lakip ang mga imahe alang sa grid. Sa duwa, kining tanan irepresentar sa 4*4 collectionView. Kung dili ka pa pamilyar sa collectionView, ania kini makuha nimo ang impormasyon nga imong gikinahanglan.

Atong i-configure ang GameController isip root controller sa aplikasyon. Ang GameController adunay usa ka collectionView nga among i-refer isip usa ka IBOutlet. Ang laing pakisayran mao ang IBAction onStartGame() nga buton, kini usa ka UIButton, makita nimo kini sa storyboard nga gitawag ug PLAY.

Usa ka gamay bahin sa pagpatuman sa mga controller:

  • Una, atong gisugdan ang duha ka nag-unang butang - ang grid: dula = MemoryGame(), ug usa ka set sa mga kard: cards = [Card]().
  • Gibutang namon ang mga inisyal nga variable ingon viewDidLoad, kini ang una nga pamaagi nga gitawag samtang nagdagan ang dula.
  • Ang collectionView gitakda nga gitago tungod kay ang tanan nga mga kard gitago hangtod nga gipugos sa gumagamit ang PLAY.
  • Sa diha nga kami mopilit sa PLAY, ang onStartGame IBAction nga seksyon magsugod, ug among ibutang ang collectionView isHidden property ngadto sa false aron ang mga card mahimong makita.
  • Matag higayon nga ang user mopili og kard, ang didSelectItemAt nga pamaagi gitawag. Sa pamaagi nga among gitawag didSelectCard aron ipatuman ang panguna nga lohika sa dula.

Ania ang katapusang pagpatuman sa 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)
    }
}

Karon maghisgot kita og gamay mahitungod sa importante nga mga protocol.

Mga protokol

Ang pagtrabaho sa mga protocol mao ang kinauyokan sa Swift programming. Ang mga protocol naghatag ug katakus sa paghubit sa mga lagda alang sa usa ka klase, istruktura, o enumeration. Kini nga prinsipyo nagtugot kanimo sa pagsulat sa modular ug extensible nga code. Sa tinuud, kini usa ka sumbanan nga among gipatuman na alang sa collectionView sa GameController. Karon maghimo kita ug kaugalingong bersyon. Ang syntax mahimong sama niini:

protocol MemoryGameProtocol {
    //protocol definition goes here
}

Nahibal-an namon nga ang usa ka protocol nagtugot kanamo sa paghubit sa mga lagda o mga panudlo alang sa pagpatuman sa usa ka klase, busa hunahunaon naton kung unsa kini. Kinahanglan nimo ang upat sa kinatibuk-an.

  • Pagsugod sa dula: memoryGameDidStart.
  • Kinahanglan nimo nga ibalik ang kard sa ubos: memoryGameShowCards.
  • Kinahanglan nimo nga ibalik ang kard sa ubos: memoryGameHideCards.
  • Katapusan sa dula: memoryGameDidEnd.

Ang tanan nga upat ka mga pamaagi mahimong ipatuman alang sa nag-unang klase, nga mao ang GameController.

memoryGameDidStart

Kung kini nga pamaagi gipadagan, ang dula kinahanglan magsugod (ang tiggamit mopilit sa PLAY). Dinhi lang nato i-reload ang sulod pinaagi sa pagtawag sa collectionView.reloadData(), nga mag-shuffle sa mga card.

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

memoryGameShowCards

Gitawag namo kini nga pamaagi gikan sa collectionSDViewSelectItemAt. Una kini nagpakita sa pinili nga kard. Dayon susiha aron tan-awon kon aduna bay dili hitupngan nga kard sa mga kardGipakita nga laray (kon ang gidaghanon sa mga kard nga gipakita kay katingad-an). Kung adunay usa, ang gipili nga kard gitandi niini. Kung managsama ang mga litrato, ang duha nga mga kard idugang sa mga kard nga Gipakita ug magpabilin nga nag-atubang. Kung lahi, ang kard nagbilin sa mga kard nga Gipakita ug ang duha gipaatubang.

memoryGameHideCards

Kung ang mga kard dili magkatugma, kini nga pamaagi gitawag ug ang mga imahe sa kard gitago.

gipakita = bakak.

memoryGameDidEnd

Kung kini nga pamaagi gitawag, kini nagpasabut nga ang tanan nga mga kard napadayag na ug naa sa mga kardGipakita nga lista: cardsShown.count = cards.count, mao nga ang dula nahuman na. Ang pamaagi gitawag nga espesipiko pagkahuman nga gitawag namon ang endGame() aron itakda ang isPlaying var sa sayup, pagkahuman gipakita ang mensahe sa katapusan sa dula. Usab alertController gigamit ingon nga usa ka timailhan alang sa controller. viewDidDisappear gitawag ug ang dula gi-reset.

Ania kung unsa ang hitsura sa tanan sa 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()
    }
}

Pagsulat sa Dula sa Memory Card sa Swift
Actually, mao ra. Mahimo nimong gamiton kini nga proyekto sa paghimo sa imong kaugalingon nga bersyon sa dula.

Malipayon nga coding!

Girekomenda sa Skillbox:

Source: www.habr.com

Idugang sa usa ka comment