Հիշողության քարտերի խաղ գրել Swift-ում

Հիշողության քարտերի խաղ գրել Swift-ում

Այս հոդվածը նկարագրում է հիշողության ուսուցման պարզ խաղի ստեղծման գործընթացը, որն ինձ շատ է դուր գալիս: Բացի ինքնին լավ լինելուց, դուք մի փոքր ավելին կսովորեք Swift դասերի և արձանագրությունների մասին, երբ գնում եք: Բայց նախքան սկսելը, եկեք հասկանանք խաղն ինքնին:

Հիշեցում. «Habr»-ի բոլոր ընթերցողների համար՝ 10 ռուբլի զեղչ «Habr» գովազդային կոդով Skillbox-ի ցանկացած դասընթացին գրանցվելիս:

Skillbox-ը խորհուրդ է տալիս. Ուսումնական առցանց դասընթաց «Մասնագիտություն Java ծրագրավորող».

Ինչպես խաղալ հիշողության քարտ

Խաղը սկսվում է քարտերի հավաքածուի ցուցադրմամբ: Նրանք պառկում են դեմքով (համապատասխանաբար՝ պատկերը ներքև): Երբ սեղմում եք որևէ մեկի վրա, պատկերը բացվում է մի քանի վայրկյանով:

Խաղացողի խնդիրն է գտնել նույն նկարներով բոլոր քարտերը: Եթե ​​առաջին քարտը բացելուց հետո շրջում եք երկրորդը և նկարները համընկնում են, երկու քարտերն էլ բաց են մնում։ Եթե ​​դրանք չեն համընկնում, ապա քարտերը կրկին փակվում են: Նպատակը ամեն ինչ բացելն է։

Ծրագրի կառուցվածքը

Այս խաղի պարզ տարբերակ ստեղծելու համար ձեզ անհրաժեշտ են հետևյալ բաղադրիչները.

  • Մեկ վերահսկիչ՝ GameController.swift:
  • Մեկ դիտում. CardCell.swift:
  • Երկու մոդել՝ MemoryGame.swift և Card.swift:
  • Main.storyboard՝ ապահովելու, որ բաղադրիչների ամբողջ փաթեթը հասանելի է:

Մենք սկսում ենք խաղի ամենապարզ բաղադրիչից՝ քարտերից։

Card.swift

Քարտի մոդելը կունենա երեք հատկություն՝ id յուրաքանչյուրը նույնականացնելու համար, բուլյան փոփոխական, որը ցույց է տալիս քարտի կարգավիճակը (թաքնված կամ բաց) և artworkURL քարտերի պատկերների համար:

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

Քարտեզների հետ օգտատերերի փոխազդեցությունը վերահսկելու համար ձեզ նաև անհրաժեշտ կլինեն հետևյալ մեթոդները.

Քարտի վրա պատկեր ցուցադրելու մեթոդ. Այստեղ մենք վերակայում ենք բոլոր հատկությունները լռելյայն: ID-ի համար մենք ստեղծում ենք պատահական id՝ զանգահարելով NSUUIS().uuidString:

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

ID քարտերի համեմատության մեթոդ.

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

Յուրաքանչյուր քարտի պատճեն ստեղծելու մեթոդ - ավելի մեծ թվով նույնականներ ստանալու համար: Այս մեթոդը կվերադարձնի նույն արժեքներով քարտը:

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

Եվ ևս մեկ մեթոդ է անհրաժեշտ քարտերը սկզբում խառնելու համար: Մենք այն կդարձնենք Array դասի ընդլայնում:

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

Եվ ահա Քարտի մոդելի կոդի ներդրումը բոլոր հատկություններով և մեթոդներով:

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

Գնացեք:

Երկրորդ մոդելը MemoryGame-ն է, այստեղ մենք սահմանել ենք 4*4 ցանց: Մոդելը կունենա այնպիսի հատկություններ, ինչպիսիք են քարտերը (քարտերի զանգված ցանցի վրա), քարտերի ցուցադրված զանգված՝ արդեն բաց քարտերով, և բուլյան փոփոխական է խաղում՝ խաղի կարգավիճակին հետևելու համար:

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

Մենք նաև պետք է մեթոդներ մշակենք ցանցի հետ օգտագործողների փոխազդեցությունը վերահսկելու համար:

Մեթոդ, որը խառնում է քարտերը ցանցում:

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

Նոր խաղ ստեղծելու մեթոդ. Այստեղ մենք կանչում ենք առաջին մեթոդը՝ սկզբնական դասավորությունը սկսելու և isPlaying փոփոխականը true դարձնելու համար:

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

Եթե ​​ցանկանում ենք վերսկսել խաղը, այնուհետև isPlaying փոփոխականը դնում ենք false և հեռացնում ենք քարտերի նախնական դասավորությունը:

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

Սեղմված քարտերը ստուգելու մեթոդ: Նրա մասին ավելի ուշ:

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

Մեթոդ, որը վերադարձնում է կոնկրետ քարտի դիրքը:

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

Ընտրված քարտի համապատասխանության ստուգում ստանդարտին:

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

Այս մեթոդը կարդում է **cardsShown** զանգվածի վերջին տարրը և վերադարձնում է չհամապատասխանող քարտը:

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

Main.storyboard-ն այսպիսի տեսք ունի.

Հիշողության քարտերի խաղ գրել Swift-ում

Սկզբում դուք պետք է կարգավորեք նոր խաղը որպես viewDidLoad, ներառյալ ցանցի պատկերները: Խաղում այս ամենը կներկայացվի 4*4 collectionView-ով։ Եթե ​​դեռ ծանոթ չեք collectionView-ին, ահա այն դուք կարող եք ստանալ անհրաժեշտ տեղեկատվությունը.

Մենք կկազմաձևենք GameController-ը որպես հավելվածի արմատային վերահսկիչ: GameController-ը կունենա collectionView, որը մենք կհղենք որպես IBOutlet: Մեկ այլ հղում վերաբերում է IBAction onStartGame() կոճակին, սա UIButton է, այն կարող եք տեսնել PLAY կոչվող ցուցատախտակի վրա:

Մի փոքր վերահսկիչների իրականացման մասին.

  • Նախ, մենք նախաստորագրում ենք երկու հիմնական օբյեկտ՝ ցանցը՝ խաղ = MemoryGame(), և մի շարք քարտեր՝ քարտեր = [Քարտ]():
  • Մենք սկզբնական փոփոխականները դնում ենք որպես viewDidLoad, սա առաջին մեթոդն է, որը կանչվում է խաղի ընթացքում:
  • collectionView-ը դրված է որպես թաքնված, քանի որ բոլոր քարտերը թաքցված են այնքան ժամանակ, մինչև օգտագործողը սեղմի PLAY:
  • Հենց որ սեղմում ենք PLAY-ը, սկսվում է onStartGame IBAction բաժինը, և collectionView isHidden հատկությունը սահմանում ենք false, որպեսզի քարտերը տեսանելի լինեն:
  • Ամեն անգամ, երբ օգտվողն ընտրում է քարտ, կոչվում է didSelectItemAt մեթոդը: Մեթոդում մենք անվանում ենք didSelectCard՝ խաղի հիմնական տրամաբանությունն իրականացնելու համար:

Ահա 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)
    }
}

Հիմա մի փոքր խոսենք կարևոր արձանագրությունների մասին։

Արձանագրություններ

Արձանագրությունների հետ աշխատելը Swift ծրագրավորման առանցքն է: Արձանագրություններն ապահովում են դասի, կառուցվածքի կամ թվարկման կանոններ սահմանելու հնարավորություն: Այս սկզբունքը թույլ է տալիս գրել մոդուլային և ընդարձակվող կոդ։ Փաստորեն, սա օրինաչափություն է, որը մենք արդեն իրականացնում ենք collectionView-ի համար GameController-ում: Հիմա եկեք պատրաստենք մեր սեփական տարբերակը։ Շարահյուսությունը կունենա հետևյալ տեսքը.

protocol MemoryGameProtocol {
    //protocol definition goes here
}

Մենք գիտենք, որ արձանագրությունը թույլ է տալիս սահմանել կանոններ կամ հրահանգներ դասի իրականացման համար, ուստի եկեք մտածենք, թե դրանք ինչ պետք է լինեն: Ընդհանուր առմամբ ձեզ հարկավոր է չորս:

  • Խաղի սկիզբ. memoryGameDidStart:
  • Դուք պետք է շրջեք քարտը դեմքով ներքև՝ memoryGameShowCards:
  • Դուք պետք է շրջեք քարտը դեմքով ներքև՝ memoryGameHideCards:
  • Խաղի ավարտը. memoryGameDidEnd:

Բոլոր չորս մեթոդները կարող են իրականացվել հիմնական դասի համար, որը GameController է:

memoryGameDidStart

Երբ այս մեթոդը գործարկվի, խաղը պետք է սկսվի (օգտագործողը սեղմում է PLAY): Այստեղ մենք պարզապես կվերբեռնենք բովանդակությունը՝ զանգահարելով collectionView.reloadData(), որը կխառնի քարտերը:

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

memoryGameShowCards

Մենք կոչում ենք այս մեթոդը collectionSDViewSelectItemAt-ից: Սկզբում այն ​​ցույց է տալիս ընտրված քարտը: Այնուհետև ստուգում է, թե արդյոք կա չհամընկնող քարտ cardsShown զանգվածում (եթե cardsShown թիվը տարօրինակ է): Եթե ​​կա մեկը, ապա ընտրված քարտը համեմատվում է դրա հետ: Եթե ​​նկարները նույնն են, երկու քարտերն էլ ավելացվում են Ցուցադրված քարտերին և մնում են դեմքով: Եթե ​​տարբեր է, ապա քարտը թողնում է քարտերը, որոնք ցուցադրվում են, և երկուսն էլ շրջված են դեմքով ներքև:

memoryGameHideCards

Եթե ​​քարտերը չեն համընկնում, այս մեթոդը կանչվում է, և քարտի պատկերները թաքցվում են:

ցուցադրված = կեղծ.

memoryGameDidEnd

Երբ այս մեթոդը կանչվում է, նշանակում է, որ բոլոր քարտերն արդեն բացահայտված են և գտնվում են cardsShown ցուցակում՝ cardsShown.count = cards.count, ուրեմն խաղն ավարտված է: Մեթոդը կոչվում է հատկապես այն բանից հետո, երբ մենք կանչեցինք endGame()՝ isPlaying var-ը false սահմանելու համար, որից հետո ցուցադրվում է խաղի ավարտի հաղորդագրությունը: Նաև alertController-ը օգտագործվում է որպես վերահսկիչի ցուցիչ: viewDidDisappear-ը կանչվում է, և խաղը վերակայվում է:

Ահա թե ինչ տեսք ունի այս ամենը 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()
    }
}

Հիշողության քարտերի խաղ գրել Swift-ում
Իրականում այսքանը: Դուք կարող եք օգտագործել այս նախագիծը խաղի ձեր սեփական տարբերակը ստեղծելու համար:

Ուրախ կոդավորում:

Skillbox-ը խորհուրդ է տալիս.

Source: www.habr.com

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