ஸ்விஃப்டில் மெமரி கார்டு கேம் எழுதுதல்

ஸ்விஃப்டில் மெமரி கார்டு கேம் எழுதுதல்

நான் மிகவும் விரும்பும் ஒரு எளிய நினைவக பயிற்சி விளையாட்டை உருவாக்கும் செயல்முறையை இந்த கட்டுரை விவரிக்கிறது. சிறப்பாக இருப்பதுடன், நீங்கள் செல்லும்போது ஸ்விஃப்ட் வகுப்புகள் மற்றும் நெறிமுறைகள் பற்றி இன்னும் கொஞ்சம் கற்றுக் கொள்வீர்கள். ஆனால் தொடங்குவதற்கு முன், விளையாட்டைப் புரிந்துகொள்வோம்.

நாங்கள் நினைவூட்டுகிறோம்: "Habr" இன் அனைத்து வாசகர்களுக்கும் - "Habr" விளம்பரக் குறியீட்டைப் பயன்படுத்தி எந்த Skillbox படிப்பிலும் சேரும்போது 10 ரூபிள் தள்ளுபடி.

Skillbox பரிந்துரைக்கிறது: கல்வி ஆன்லைன் படிப்பு "தொழில் ஜாவா டெவலப்பர்".

மெமரி கார்டை விளையாடுவது எப்படி

விளையாட்டு அட்டைகளின் தொகுப்பின் ஆர்ப்பாட்டத்துடன் தொடங்குகிறது. அவர்கள் முகம் கீழே படுத்துக் கொள்கிறார்கள் (முறையே, படம் கீழே). ஏதேனும் ஒன்றைக் கிளிக் செய்தால், படம் சில நொடிகளுக்குத் திறக்கும்.

ஒரே படங்களுடன் அனைத்து அட்டைகளையும் கண்டுபிடிப்பதே வீரரின் பணி. முதல் அட்டையைத் திறந்த பிறகு, இரண்டாவது அட்டையைத் திருப்பி, படங்கள் பொருந்தினால், இரண்டு அட்டைகளும் திறந்தே இருக்கும். அவை பொருந்தவில்லை என்றால், அட்டைகள் மீண்டும் மூடப்படும். எல்லாவற்றையும் திறப்பதே குறிக்கோள்.

திட்ட அமைப்பு

இந்த விளையாட்டின் எளிய பதிப்பை உருவாக்க, உங்களுக்கு பின்வரும் கூறுகள் தேவை:

  • ஒரு கட்டுப்படுத்தி: GameController.swift.
  • ஒரு பார்வை: CardCell.swift.
  • இரண்டு மாதிரிகள்: MemoryGame.swift மற்றும் Card.swift.
  • Main.storyboard கூறுகளின் முழு தொகுப்பும் இருப்பதை உறுதிசெய்யும்.

நாங்கள் விளையாட்டின் எளிய கூறுகளான அட்டைகளுடன் தொடங்குகிறோம்.

Card.swift

கார்டு மாதிரி மூன்று பண்புகளைக் கொண்டிருக்கும்: ஒவ்வொன்றையும் அடையாளம் காண ஐடி, கார்டின் நிலையைக் குறிப்பிட பூலியன் மாறி (மறைக்கப்பட்ட அல்லது திறந்த) மற்றும் கார்டுகளில் உள்ள படங்களுக்கான ஆர்ட்வொர்க்URL.

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

வரைபடங்களுடனான பயனர் தொடர்புகளைக் கட்டுப்படுத்த உங்களுக்கு இந்த முறைகளும் தேவைப்படும்:

அட்டையில் படத்தைக் காண்பிக்கும் முறை. இங்கே நாம் எல்லா பண்புகளையும் இயல்புநிலைக்கு மீட்டமைக்கிறோம். ஐடிக்கு, NSUUIS(.uuidString) ஐ அழைப்பதன் மூலம் சீரற்ற ஐடியை உருவாக்குகிறோம்.

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)    
}
 
init(card: Card) {        
    self.id = card.id        
    self.shown = card.shown        
    self.artworkURL = card.artworkURL    
}

தொடக்கத்தில் கார்டுகளை மாற்றுவதற்கு மேலும் ஒரு முறை தேவை. நாங்கள் அதை வரிசை வகுப்பின் நீட்டிப்பாக மாற்றுவோம்.

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 கட்டத்தை அமைக்கிறோம். மாடலில் கார்டுகள் (கட்டத்தில் உள்ள கார்டுகளின் வரிசை), ஏற்கனவே திறந்திருக்கும் கார்டுகளுடன் கூடிய அட்டைகள் காண்பிக்கப்படும் வரிசை மற்றும் விளையாட்டின் நிலையைக் கண்காணிக்க ஒரு பூலியன் மாறி isPlaying போன்ற பண்புகளைக் கொண்டிருக்கும்.

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 இது போல் தெரிகிறது:

ஸ்விஃப்டில் மெமரி கார்டு கேம் எழுதுதல்

தொடக்கத்தில், கட்டத்திற்கான படங்கள் உட்பட, கட்டுப்படுத்தியில் புதிய கேமை viewDidLoad ஆக அமைக்க வேண்டும். விளையாட்டில், இவை அனைத்தும் 4*4 சேகரிப்பு பார்வையால் குறிக்கப்படும். சேகரிப்பு பார்வையை நீங்கள் இன்னும் அறிந்திருக்கவில்லை என்றால், இதோ உங்களுக்கு தேவையான தகவலை நீங்கள் பெறலாம்.

கேம்கண்ட்ரோலரை ஆப்ஸின் ரூட் கன்ட்ரோலராக உள்ளமைப்போம். கேம்கண்ட்ரோலரில் ஒரு சேகரிப்பு காட்சி இருக்கும், அதை நாங்கள் IBOutlet என்று குறிப்பிடுவோம். மற்றொரு குறிப்பு IBAction onStartGame() பொத்தான், இது ஒரு UIButton, நீங்கள் அதை PLAY எனப்படும் ஸ்டோரிபோர்டில் பார்க்கலாம்.

கட்டுப்படுத்திகளை செயல்படுத்துவது பற்றி கொஞ்சம்:

  • முதலில், நாம் இரண்டு முக்கிய பொருட்களை துவக்குகிறோம் - கட்டம்: விளையாட்டு = MemoryGame(), மற்றும் அட்டைகளின் தொகுப்பு: அட்டைகள் = [Card]().
  • ஆரம்ப மாறிகளை viewDidLoad ஆக அமைத்துள்ளோம், இது விளையாட்டு இயங்கும் போது அழைக்கப்படும் முதல் முறையாகும்.
  • சேகரிப்பு காட்சி மறைக்கப்பட்டதாக அமைக்கப்பட்டுள்ளது, ஏனெனில் பயனர் PLAY ஐ அழுத்தும் வரை அனைத்து அட்டைகளும் மறைக்கப்படும்.
  • நாங்கள் PLAY ஐ அழுத்தியவுடன், onStartGame IBAction பிரிவு தொடங்கும், மேலும் அட்டைகள் தெரியும் வகையில் சேகரிப்பு காட்சி isHidden சொத்து தவறு என அமைக்கிறோம்.
  • ஒவ்வொரு முறையும் பயனர் கார்டைத் தேர்ந்தெடுக்கும்போது, ​​didSelectItemAt முறை அழைக்கப்படுகிறது. முக்கிய கேம் லாஜிக்கை செயல்படுத்த நாங்கள் didSelectCard என்று அழைக்கும் முறையில்.

இறுதி கேம்கண்ட்ரோலர் செயல்படுத்தல் இங்கே:

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

இப்போது முக்கியமான நெறிமுறைகளைப் பற்றி கொஞ்சம் பேசலாம்.

நெறிமுறைகள்

நெறிமுறைகளுடன் பணிபுரிவது ஸ்விஃப்ட் நிரலாக்கத்தின் மையமாகும். நெறிமுறைகள் ஒரு வகுப்பு, கட்டமைப்பு அல்லது கணக்கீடுக்கான விதிகளை வரையறுக்கும் திறனை வழங்குகின்றன. இந்த கொள்கை மட்டு மற்றும் நீட்டிக்கக்கூடிய குறியீட்டை எழுத உங்களை அனுமதிக்கிறது. உண்மையில், இது கேம்கண்ட்ரோலரில் சேகரிப்புப் பார்வைக்காக நாங்கள் ஏற்கனவே செயல்படுத்தி வருகிறோம். இப்போது எங்கள் சொந்த பதிப்பை உருவாக்குவோம். தொடரியல் இப்படி இருக்கும்:

protocol MemoryGameProtocol {
    //protocol definition goes here
}

ஒரு வகுப்பைச் செயல்படுத்துவதற்கான விதிகள் அல்லது வழிமுறைகளை வரையறுக்க ஒரு நெறிமுறை அனுமதிக்கிறது என்பதை நாங்கள் அறிவோம், எனவே அவை என்னவாக இருக்க வேண்டும் என்பதைப் பற்றி சிந்திப்போம். உங்களுக்கு மொத்தம் நான்கு தேவை.

  • கேம் ஆரம்பம்: memoryGameDidStart.
  • நீங்கள் கார்டை முகத்தை கீழே திருப்ப வேண்டும்: memoryGameShowCards.
  • நீங்கள் கார்டை முகத்தை கீழே திருப்ப வேண்டும்: memoryGameHideCards.
  • விளையாட்டு முடிவு: memoryGameDidEnd.

கேம் கன்ட்ரோலர் என்ற பிரதான வகுப்பிற்கு நான்கு முறைகளையும் செயல்படுத்தலாம்.

memoryGameDidStart

இந்த முறை இயங்கும் போது, ​​விளையாட்டு தொடங்க வேண்டும் (பயனர் PLAY ஐ அழுத்துகிறார்). இங்கே சேகரிப்புView.reloadData() ஐ அழைப்பதன் மூலம் உள்ளடக்கத்தை மீண்டும் ஏற்றுவோம், இது கார்டுகளை மாற்றும்.

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

மெமரி கேம் ஷோ கார்டுகள்

சேகரிப்புSDViewSelectItemAt இலிருந்து இந்த முறையை அழைக்கிறோம். முதலில் அது தேர்ந்தெடுக்கப்பட்ட அட்டையைக் காட்டுகிறது. கார்ட்ஸ்ஷோன் அணிவரிசையில் (காட்டப்பட்ட கார்டுகளின் எண்ணிக்கை ஒற்றைப்படையாக இருந்தால்) பொருந்தாத கார்டு உள்ளதா என்பதைச் சரிபார்க்கிறது. ஒன்று இருந்தால், தேர்ந்தெடுக்கப்பட்ட அட்டை அதனுடன் ஒப்பிடப்படுகிறது. படங்கள் ஒரே மாதிரியாக இருந்தால், இரண்டு கார்டுகளும் காட்டப்படும் கார்டுகளில் சேர்க்கப்பட்டு முகத்தை நோக்கி இருக்கும். வித்தியாசமாக இருந்தால், கார்டு காட்டப்படும் மற்றும் இரண்டும் முகம் கீழே திரும்பும்.

நினைவக விளையாட்டு மறை அட்டைகள்

அட்டைகள் பொருந்தவில்லை என்றால், இந்த முறை அழைக்கப்படுகிறது மற்றும் அட்டை படங்கள் மறைக்கப்படும்.

காட்டப்பட்ட = பொய்.

memoryGameDidEnd

இந்த முறை அழைக்கப்படும் போது, ​​அனைத்து அட்டைகளும் ஏற்கனவே வெளிப்படுத்தப்பட்டு, கார்டுகள் காண்பிக்கப்படும் பட்டியலில் உள்ளன: cardsShown.count = cards.count, எனவே விளையாட்டு முடிந்தது. isPlaying var ஐ தவறு என அமைக்க endGame() ஐ அழைத்த பிறகு இந்த முறை அழைக்கப்படுகிறது, அதன் பிறகு விளையாட்டு முடிவு செய்தி காட்டப்படும். அலெர்ட்கண்ட்ரோலர் கட்டுப்படுத்திக்கான குறிகாட்டியாகவும் பயன்படுத்தப்படுகிறது. viewDidDisappear அழைக்கப்படுகிறது மற்றும் விளையாட்டு மீட்டமைக்கப்பட்டது.

கேம்கண்ட்ரோலரில் இது எப்படி இருக்கும் என்பது இங்கே:

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

ஸ்விஃப்டில் மெமரி கார்டு கேம் எழுதுதல்
உண்மையில், அவ்வளவுதான். விளையாட்டின் உங்கள் சொந்த பதிப்பை உருவாக்க இந்தத் திட்டத்தைப் பயன்படுத்தலாம்.

மகிழ்ச்சியான குறியீட்டு!

Skillbox பரிந்துரைக்கிறது:

ஆதாரம்: www.habr.com

கருத்தைச் சேர்