Manoratra lalao karatra fitadidiana amin'ny Swift

Manoratra lalao karatra fitadidiana amin'ny Swift

Ity lahatsoratra ity dia mamaritra ny fizotran'ny famoronana lalao fanofanana fahatsiarovana tsotra izay tena tiako. Ankoatra ny maha-tsara azy dia hianatra bebe kokoa momba ny kilasy Swift sy ny protocols ianao rehefa mandeha. Fa alohan'ny hanombohantsika dia aoka isika hahatakatra ny lalao mihitsy.

Mampahatsiahy izahay: ho an'ny mpamaky rehetra ny "Habr" - fihenam-bidy 10 roubles rehefa misoratra anarana amin'ny taranja Skillbox rehetra mampiasa ny code promotional "Habr".

Skillbox dia manoro hevitra: Fampianarana an-tserasera "Profession Java Developer".

Lalao Memory Card

Ny lalao dia manomboka amin'ny fampisehoana karatra maromaro. Mandry miankohoka izy ireo (sary midina). Rehefa manindry na iza na iza ianao dia misokatra segondra vitsy ny sary.

Ny asan'ny mpilalao dia ny mitady karatra rehetra mitovy sary. Raha toa ka avadikao ny karatra faharoa aorian'ny fanokafana ny karatra voalohany ary mifanandrify ny sary, dia mbola misokatra ny karatra roa. Raha tsy mifanaraka izy ireo dia hikatona indray ny karatra. Ny tanjona dia ny hanokatra ny zava-drehetra.

Rafitra tetikasa

Mba hamoronana dikan-teny tsotra amin'ity lalao ity dia mila ireto singa manaraka ireto ianao:

  • Mpifehy iray: GameController.swift.
  • Fijery iray: CardCell.swift.
  • Modely roa: MemoryGame.swift sy Card.swift.
  • Main.storyboard mba hahazoana antoka fa misy ny fitambaran'ny singa rehetra.

Manomboka amin'ny singa tsotra indrindra amin'ny lalao isika, dia ny karatra.

Card.swift

Ny maodelin'ny karatra dia hanana toetra telo: id hamantarana ny tsirairay, faribolana boolean aseho hamaritana ny satan'ny karatra (miafina na misokatra), ary artworkURL ho an'ny sary eo amin'ny karatra.

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

Mila ireto fomba ireto koa ianao hifehezana ny fifandraisan'ny mpampiasa amin'ny sari-tany:

Fomba fanehoana sary amin'ny karatra. Eto dia averinay ho default ny fananana rehetra. Ho an'ny id dia mamorona id kisendrasendra izahay amin'ny fiantsoana ny NSUUIS().uuidString.

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

Fomba fampitahana kara-panondro.

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

Fomba hamoronana dika mitovy amin'ny karatra tsirairay - mba hahazoana isa mitovy mitovy. Ity fomba ity dia hamerina karatra misy sanda mitovy.

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

Ary ilaina ny fomba iray hafa hanodinana ny karatra eo am-piandohana. Hanao fanitarana ny kilasy Array izahay.

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

Ary eto ny fampiharana ny kaody ho an'ny modely Card miaraka amin'ny fananana sy ny fomba rehetra.

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

Mandehana.

Ny maodely faharoa dia MemoryGame, eto dia mametraka grid 4 * 4 izahay. Ny maodely dia hanana fananana toy ny karatra (karatra maromaro eo amin'ny grid), karatra aseho miaraka amin'ny karatra efa misokatra, ary ny boolean variable isPlaying hanaraha-maso ny satan'ny lalao.

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

Mila mamolavola fomba hifehezana ny fifandraisan'ny mpampiasa amin'ny grid ihany koa isika.

Fomba iray manodinkodina karatra amin'ny grid.

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

Fomba hamoronana lalao vaovao. Eto isika dia miantso ny fomba voalohany hanombohana ny drafitra voalohany ary manomboka ny fari-piadidiana isPlaying ho marina.

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

Raha te hamerina ny lalao isika, dia apetrakay ho diso ny fari-piadidiana isPlaying ary esory ny fisehon'ny karatra voalohany.

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

Fomba fanamarinana ny karatra voakitika. Bebe kokoa momba azy taty aoriana.

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

Fomba iray mamerina ny toeran'ny karatra manokana.

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

Fanamarinana ny fanarahana ny karatra voafantina amin'ny fenitra.

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

Ity fomba ity dia mamaky ny singa farany ao amin'ny **cardsShown** array ary mamerina ny karatra tsy mifanentana.

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

Main.storyboard dia toa izao:

Manoratra lalao karatra fitadidiana amin'ny Swift

Amin'ny voalohany dia mila mametraka ny lalao vaovao ho viewDidLoad ao amin'ny controller ianao, anisan'izany ny sary ho an'ny grid. Ao amin'ny lalao, izany rehetra izany dia hisolo tena ny 4*4 collectionView. Raha mbola tsy zatra amin'ny collectionView ianao dia ity afaka mahazo ny vaovao ilainao ianao.

Hamboarinay ny GameController ho mpanara-maso ny fakany. Ny GameController dia hanana collectionView izay holazainay ho IBOutlet. Ny fanondroana iray hafa dia ny bokotra IBAction onStartGame(), ity dia UIButton, azonao jerena ao amin'ny solaitrabe antsoina hoe PLAY.

Kely momba ny fampiharana ny controllers:

  • Voalohany, manomboka zavatra roa lehibe isika - ny grid: lalao = MemoryGame(), ary karatra maromaro: karatra = [Card]().
  • Nametraka ny variables voalohany ho viewDidLoad izahay, ity no fomba voalohany antsoina rehefa mandeha ny lalao.
  • Ny collectionView dia natao miafina satria nafenina avokoa ny karatra rehetra mandra-panery ny mpampiasa ny PLAY.
  • Raha vantany vao manindry ny PLAY izahay dia manomboka ny fizarana onStartGame IBAction, ary apetrakay ho diso ny fananana CollectionView isHidden mba ho hita ny karatra.
  • Isaky ny mifidy karatra ny mpampiasa dia antsoina ny fomba didSelectItemAt. Amin'ny fomba antsoina hoe didSelectCard hampihatra ny lojika lalao lehibe.

Ity ny fampiharana GameController farany:

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

Andeha isika hiresaka kely momba ny protocols manan-danja.

Protocols

Ny fiasana amin'ny protocols no fototry ny fandaharana Swift. Ny protocols dia manome fahafahana mamaritra fitsipika ho an'ny kilasy, rafitra, na fanisana. Ity fitsipika ity dia ahafahanao manoratra code modular sy extensible. Raha ny marina, ity dia lamina efa apetrakay ho an'ny collectionView ao amin'ny GameController. Andeha isika hanao ny dikan-tsika manokana. Ny syntax dia ho toy izao:

protocol MemoryGameProtocol {
    //protocol definition goes here
}

Fantatsika fa ny protocol dia mamela antsika hamaritra fitsipika na torolalana amin'ny fampiharana kilasy iray, ka andeha hojerentsika ny tokony ho izy. Mila efatra ianao amin'ny fitambarany.

  • Manomboka ny lalao: memoryGameDidStart.
  • Mila avadika midina ny karatra: memoryGameShowCards.
  • Mila avadika midina ny karatra: memoryGameHideCards.
  • Famaranana ny lalao: memoryGameDidEnd.

Ireo fomba efatra rehetra dia azo ampiharina amin'ny kilasy lehibe, dia ny GameController.

memoryGameDidStart

Rehefa mandeha io fomba io dia tokony hanomboka ny lalao (manindry ny PLAY ny mpampiasa). Eto isika dia hamerina fotsiny ny atiny amin'ny fiantsoana collectionView.reloadData(), izay hanodina ny karatra.

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

memoryGameShowCards

Antsoinay ity fomba ity avy amin'ny collectionSDViewSelectItemAt. Voalohany dia mampiseho ny karatra voafantina. Dia jereo raha misy karatra tsy mifanandrify ao amin'ny laharan'ny cardsShown (raha toa hafahafa ny isan'ny karatra aseho). Raha misy iray dia ampitahaina aminy ny karatra voafantina. Raha mitovy ny sary, dia ampiana amin'ny karatra Aseho ny karatra roa ary mijanona mitsangana. Raha tsy mitovy dia mamela karatra Aseho ny karatra ary avadika miondrika izy roa.

MemoryGameHideCards

Raha tsy mifanaraka ny karatra, dia antsoina io fomba io ary nafenina ny sary karatra.

aseho = diso.

memoryGameDidEnd

Rehefa antsoina io fomba io dia midika izany fa efa nambara ny karatra rehetra ary ao anatin'ny lisitry ny karatra aseho: cardsShown.count = cards.count, ka vita ny lalao. Ny fomba dia antsoina manokana taorian'ny niantsoanay endGame() hametraka ny isPlaying var ho diso, ary avy eo dia aseho ny hafatra fiafaran'ny lalao. Ny alertController koa dia ampiasaina ho famantarana ny controller. Nantsoina ny viewDidDisappear ary averina ny lalao.

Toy izao ny endriny rehetra ao amin'ny 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()
    }
}

Manoratra lalao karatra fitadidiana amin'ny Swift
Raha ny marina dia izay ihany. Azonao atao ny mampiasa ity tetikasa ity mba hamoronana ny dikan-teninao manokana amin'ny lalao.

Faly coding!

Skillbox dia manoro hevitra:

Source: www.habr.com

Add a comment