የማህደረ ትውስታ ካርዶች ጨዋታ በስዊፍት ውስጥ መጻፍ

የማህደረ ትውስታ ካርዶች ጨዋታ በስዊፍት ውስጥ መጻፍ

ይህ ጽሑፍ እኔ በጣም የምወደው ቀላል የማስታወስ ስልጠና ጨዋታ የመፍጠር ሂደትን ይገልጻል። በራሱ ጥሩ ከመሆን በተጨማሪ በሚሄዱበት ጊዜ ስለ ስዊፍት ትምህርቶች እና ፕሮቶኮሎች ትንሽ ተጨማሪ ይማራሉ ። ከመጀመራችን በፊት ግን ጨዋታውን ራሱ እንረዳው።

እኛ እናስታውስዎታለን- ለሁሉም የ "ሀብር" አንባቢዎች - የ "Habr" የማስተዋወቂያ ኮድን በመጠቀም በማንኛውም የ Skillbox ኮርስ ውስጥ ሲመዘገቡ የ 10 ሩብልስ ቅናሽ.

Skillbox ይመክራል፡ ትምህርታዊ የመስመር ላይ ኮርስ "ሙያ ጃቫ ገንቢ".

የማህደረ ትውስታ ካርድ እንዴት እንደሚጫወት

ጨዋታው በካርዶች ስብስብ ማሳያ ይጀምራል። እነሱ ፊት ለፊት ይተኛሉ (በቅደም ተከተል ፣ ምስል ወደ ታች)። ማንኛውንም ጠቅ ሲያደርጉ ምስሉ ለጥቂት ሰከንዶች ይከፈታል.

የተጫዋቹ ተግባር ሁሉንም ተመሳሳይ ስዕሎች ያላቸውን ካርዶች ማግኘት ነው. የመጀመሪያውን ካርድ ከከፈቱ በኋላ ሁለተኛውን ካጠፉት እና ስዕሎቹ ከተዛመዱ ሁለቱም ካርዶች ክፍት እንደሆኑ ይቆያሉ። እነሱ የማይዛመዱ ከሆነ, ካርዶቹ እንደገና ይዘጋሉ. ግቡ ሁሉንም ነገር መክፈት ነው.

የፕሮጀክት መዋቅር

የዚህ ጨዋታ ቀላል ስሪት ለመፍጠር የሚከተሉትን ክፍሎች ያስፈልግዎታል:

  • አንድ መቆጣጠሪያ: GameController.swift.
  • አንድ እይታ: CardCell.swift.
  • ሁለት ሞዴሎች: MemoryGame.swift እና Card.swift.
  • ዋናው የታሪክ ሰሌዳ የጠቅላላው ክፍሎች ስብስብ መገኘቱን ለማረጋገጥ።

በጨዋታው በጣም ቀላሉ አካል ማለትም በካርዶቹ እንጀምራለን.

ካርድ.ፈጣን

የካርድ ሞዴሉ ሶስት ባህሪያት ይኖረዋል፡ እያንዳንዱን ለመለየት መታወቂያ፣ የካርዱን ሁኔታ የሚገልጽ የቦሊያን ተለዋዋጭ (የተደበቀ ወይም ክፍት) እና በካርዶቹ ላይ ላሉት ምስሎች artworkURL።

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    
}

እና በጅማሬ ላይ ካርዶቹን ለመደባለቅ አንድ ተጨማሪ ዘዴ ያስፈልጋል. የ 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 ተለዋዋጭን ወደ እውነት ለመጀመር የመጀመሪያውን ዘዴ እንጠራዋለን.

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

ጨዋታውን እንደገና ማስጀመር ከፈለግን ከዚያ የ isPlaying ተለዋዋጭ ወደ ሐሰት እናዘጋጃለን እና የካርዶቹን የመጀመሪያ አቀማመጥ እናስወግደዋለን።

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
}

ይህ ዘዴ በ ** ካርዶች የሚታየው *** ድርድር ውስጥ የመጨረሻውን አካል ያነባል እና የማይዛመድ ካርዱን ይመልሳል።

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 ስብስብ እይታ ይወከላል. የስብስብ እይታን ገና የማታውቁት ከሆነ፣ እዚህ አለ። የሚፈልጉትን መረጃ ማግኘት ይችላሉ።.

GameControllerን እንደ የመተግበሪያው ስር ተቆጣጣሪ እናዋቅረዋለን። GameController እንደ IBOutlet የምንጠቅሰው የስብስብ እይታ ይኖረዋል። ሌላው ማጣቀሻ የ IBAction onStartGame () አዝራር ነው, ይህ UIButton ነው, እርስዎ PLAY በተባለው የታሪክ ሰሌዳ ላይ ሊያዩት ይችላሉ.

ስለ ተቆጣጣሪዎች አተገባበር ትንሽ፡-

  • በመጀመሪያ, ሁለት ዋና ነገሮችን እናስጀምራለን - ፍርግርግ: ጨዋታ = MemoryGame (), እና የካርድ ስብስብ: ካርዶች = [ካርድ] ().
  • የመጀመሪያ ተለዋዋጮችን እንደ viewDidLoad እናዘጋጃለን ፣ ይህ ጨዋታው በሚሰራበት ጊዜ የሚጠራው የመጀመሪያው ዘዴ ነው።
  • የስብስብ እይታ ተደብቋል ምክንያቱም ተጠቃሚው ተጫወትን እስኪጫን ድረስ ሁሉም ካርዶች ተደብቀዋል።
  • ልክ PLAYን እንደጫንን የ onStartGame IBAction ክፍል ይጀምራል እና ካርዶቹ እንዲታዩ የስብስብ እይታ ስውር ንብረትን ወደ ሃሰት እናስቀምጣለን።
  • ተጠቃሚው ካርድ በመረጠ ቁጥር የ 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)
    }
}

አሁን ስለ ጠቃሚ ፕሮቶኮሎች ትንሽ እንነጋገር.

ፕሮቶኮሎች

ከፕሮቶኮሎች ጋር መሥራት የስዊፍት ፕሮግራሚንግ ዋና አካል ነው። ፕሮቶኮሎች ለክፍል፣ መዋቅር ወይም ቆጠራ ደንቦችን የመግለጽ ችሎታ ይሰጣሉ። ይህ መርህ ሞጁል እና ሊወጣ የሚችል ኮድ እንዲጽፉ ይፈቅድልዎታል. በእርግጥ ይህ በGameController ውስጥ ለክምችት እይታ አስቀድመን ተግባራዊ እያደረግን ያለነው ስርዓተ-ጥለት ነው። አሁን የራሳችንን ስሪት እንሥራ. አገባብ የሚከተለውን ይመስላል።

protocol MemoryGameProtocol {
    //protocol definition goes here
}

ፕሮቶኮል አንድን ክፍል ለመተግበር ደንቦችን ወይም መመሪያዎችን ለመግለጽ እንደሚፈቅድልን እናውቃለን, ስለዚህ ምን መሆን እንዳለባቸው እናስብ. በአጠቃላይ አራት ያስፈልግዎታል.

  • የጨዋታ መጀመሪያ: memoryGameDidStart.
  • ካርዱን ወደ ታች ማዞር ያስፈልግዎታል: memoryGameShowCards.
  • ካርዱን ወደ ታች ማዞር ያስፈልግዎታል: memoryGameHideCards.
  • የጨዋታ መጨረሻ: memoryGameDidEnd.

አራቱም ዘዴዎች ለዋናው ክፍል ሊተገበሩ ይችላሉ, እሱም GameController ነው.

ማህደረ ትውስታGameDidStart

ይህ ዘዴ ሲሰራ ጨዋታው መጀመር አለበት (ተጠቃሚው PLAY ን ይጫኑ)። እዚህ በቀላሉ ወደ collectionView.reloadData() በመደወል ይዘቱን እንደገና እንጭናለን ይህም ካርዶቹን ያዋህዳል።

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

ማህደረ ትውስታየጨዋታ ማሳያ ካርዶች

ይህንን ዘዴ ከስብስብ እንጠራዋለንSDViewSelectItemAt። በመጀመሪያ የተመረጠውን ካርድ ያሳያል. ከዚያ በካርዶች የሚታየው ድርድር ውስጥ የማይዛመድ ካርድ እንዳለ ያረጋግጡ (የካርዶች ብዛት ያልተለመደ ከሆነ)። አንድ ካለ, የተመረጠው ካርድ ከእሱ ጋር ይነጻጸራል. ስዕሎቹ ተመሳሳይ ከሆኑ ሁለቱም ካርዶች ወደ ካርዶች ይታከላሉ እና ፊት ለፊት ይቆያሉ። የተለየ ከሆነ ካርዱ ካርዶችን ይተዋል እና ሁለቱም ወደ ታች ይቀየራሉ።

የማስታወሻ ጨዋታHideCard

ካርዶቹ የማይዛመዱ ከሆነ, ይህ ዘዴ ይባላል እና የካርድ ምስሎች ተደብቀዋል.

ታይቷል = ውሸት።

ማህደረ ትውስታGameDidEnd

ይህ ዘዴ ሲጠራ ሁሉም ካርዶች ቀድሞውኑ ተገለጡ እና በካርዶች ውስጥ ናቸው ማለት ነው የሚታየው ዝርዝር: cardsShown.count = cards.count, ስለዚህ ጨዋታው አልቋል. ዘዴው በተለይ endGame () ከጠራን በኋላ isPlaying var ወደ ሐሰት ለማዘጋጀት ይጠራል ፣ ከዚያ በኋላ የጨዋታው የመጨረሻ መልእክት ይታያል። እንዲሁም ማንቂያ መቆጣጠሪያ ለመቆጣጠሪያው እንደ አመላካች ጥቅም ላይ ይውላል. ViewDisappear ተጠርቷል እና ጨዋታው ዳግም ተጀምሯል።

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

የማህደረ ትውስታ ካርዶች ጨዋታ በስዊፍት ውስጥ መጻፍ
በእውነቱ፣ ያ ብቻ ነው። የእራስዎን የጨዋታውን ስሪት ለመፍጠር ይህንን ፕሮጀክት መጠቀም ይችላሉ።

መልካም ኮድ መስጠት!

Skillbox ይመክራል፡

ምንጭ: hab.com

አስተያየት ያክሉ