Swift ۾ ميموري ڪارڊ گيم لکڻ

Swift ۾ ميموري ڪارڊ گيم لکڻ

هي آرٽيڪل هڪ سادي ميموري ٽريننگ راند ٺاهڻ جي عمل کي بيان ڪري ٿو جيڪا مون کي واقعي پسند آهي. پاڻ ۾ سٺو هجڻ سان گڏ، توهان سوفٹ ڪلاس ۽ پروٽوڪول بابت ٿورو وڌيڪ سکندا جيئن توهان وڃو. پر ان کان اڳ جو اسان شروع ڪريون، اچو ته راند کي سمجھون.

اسان توهان کي ياد ڏياريون ٿا: "Habr" جي سڀني پڙهندڙن لاءِ - 10 روبل جي رعايت جڏهن "Habr" پروموشنل ڪوڊ استعمال ڪندي ڪنهن به اسڪل باڪس ڪورس ۾ داخلا.

Skillbox سفارش ڪري ٿو: تعليمي آن لائين ڪورس "پروفيشنل جاوا ڊولپر".

ميموري ڪارڊ ڪيئن کيڏجي

راند شروع ٿئي ٿي ڪارڊ جي هڪ سيٽ جي مظاهري سان. اهي منهن هيٺ ڪوڙ ڪن ٿا (ترتيب، تصوير هيٺ). جڏهن توهان ڪنهن هڪ تي ڪلڪ ڪندا آهيو، تصوير چند سيڪنڊن لاءِ کلي ٿي.

پليئر جو ڪم ساڳيو تصويرن سان سڀني ڪارڊن کي ڳولڻ آهي. جيڪڏهن، پهريون ڪارڊ کولڻ کان پوء، توهان ٻئي کي ڦيرايو ۽ تصويرون ملن ٿيون، ٻئي ڪارڊ کليل رهندا. جيڪڏهن اهي ملن نه ٿا، ڪارڊ ٻيهر بند ٿي ويا آهن. مقصد هر شي کي کولڻ آهي.

منصوبي جي جوڙجڪ

هن راند جو هڪ سادي نسخو ٺاهڻ لاء توهان کي هيٺين حصن جي ضرورت آهي:

  • ھڪڙو ڪنٽرولر: GameController.swift.
  • ھڪڙي ڏسو: CardCell.swift.
  • ٻه ماڊل: MemoryGame.swift ۽ Card.swift.
  • Main.storyboard يقيني بڻائڻ لاءِ ته اجزاء جو پورو سيٽ موجود آهي.

اسان راند جي آسان ترين جزو سان شروع ڪريون ٿا، ڪارڊ.

ڪارڊ، تيز

ڪارڊ جي ماڊل ۾ ٽي خاصيتون هونديون: هر هڪ کي سڃاڻڻ لاءِ id، هڪ بولين متغير ڏيکاريل آهي ڪارڊ جي حالت بيان ڪرڻ لاءِ (لڪيل يا کليل)، ۽ ڪارڊ تي تصويرن لاءِ آرٽ ورڪ URL.

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

توهان کي انهن طريقن جي پڻ ضرورت پوندي صارف جي رابطي کي ڪنٽرول ڪرڻ لاءِ نقشن سان:

ڪارڊ تي تصوير ڏيکارڻ جو طريقو. هتي اسان سڀني ملڪيتن کي ڊفالٽ تي ري سيٽ ڪيو. id لاءِ، اسان NSUUIS().uuidString کي ڪال ڪري هڪ بي ترتيب id ٺاهيندا آهيون.

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 گرڊ مقرر ڪيو آهي. ماڊل ۾ خاصيتون هونديون جيئن ته ڪارڊ (گرڊ تي ڪارڊن جو هڪ صف)، هڪ ڪارڊ ڏيکاريو ويو صفن سان گڏ ڪارڊ اڳ ۾ ئي کليل آهن، ۽ هڪ بوليان متغير آهي راند جي حالت کي ٽريڪ ڪرڻ لاءِ.

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 variable to true.

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

جيڪڏهن اسان راند کي ٻيهر شروع ڪرڻ چاهيون ٿا، پوءِ اسان isPlaying variable کي غلط تي سيٽ ڪيو ۽ ڪارڊ جي شروعاتي ترتيب کي ختم ڪيو.

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 سان، هتي اهو آهي توهان کي گهربل معلومات حاصل ڪري سگهو ٿا.

اسان GameController کي ايپليڪيشن جي روٽ ڪنٽرولر طور ترتيب ڏينداسين. GameController وٽ ھڪڙو ڪليڪشن ويو ھوندو جنھن کي اسين IBOutlet طور حوالو ڏينداسين. ٻيو حوالو آهي IBAction onStartGame() بٽڻ، هي هڪ UIButton آهي، توهان ان کي PLAY نالي ڪهاڻي بورڊ ۾ ڏسي سگهو ٿا.

ڪنٽرولرز جي عمل جي باري ۾ ٿورو:

  • پهرين، اسان ٻه مکيه شيون شروع ڪيون ٿا - گرڊ: راند = MemoryGame ()، ۽ ڪارڊ جو هڪ سيٽ: ڪارڊ = [ڪارڊ] ().
  • اسان شروعاتي متغيرن کي viewDidLoad طور مقرر ڪيو، اھو پھريون طريقو آھي جنھن کي سڏيو ويندو آھي جڏھن راند ھلندي آھي.
  • CollectionView لڪايو ويو آهي ڇاڪاڻ ته سڀئي ڪارڊ لڪيل آهن جيستائين صارف PLAY کي دٻائي.
  • جيئن ئي اسان PLAY کي دٻايو، onStartGame IBAction سيڪشن شروع ٿئي ٿو، ۽ اسان ڪليڪشن View isHidden ملڪيت کي غلط تي سيٽ ڪريون ٿا ته جيئن ڪارڊ ظاهر ٿي سگهن.
  • هر دفعي صارف هڪ ڪارڊ چونڊيو، 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.

memoryGameDidStart

جڏهن هي طريقو هلايو ويندو آهي، راند شروع ٿيڻ گهرجي (استعمال ڪندڙ PLAY کي دٻائي ٿو). هتي اسان صرف collectionView.reloadData() کي ڪال ڪندي مواد کي ٻيهر لوڊ ڪنداسين، جيڪو ڪارڊ کي ڦيرائي ڇڏيندو.

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

ميموري گيم شو ڪارڊ

اسان هن طريقي کي گڏ ڪريون ٿا SDViewSelectItemAt کان. پهرين اهو چونڊيو ڪارڊ ڏيکاري ٿو. پوءِ چيڪ ڪريو ته ڇا ڪارڊ ڏيکاريل صف ۾ بي مثال ڪارڊ آھي (جيڪڏھن ڏيکاريل ڪارڊن جو تعداد بي مثال آھي). جيڪڏھن ھڪڙو آھي، منتخب ٿيل ڪارڊ ان سان مقابلو ڪيو ويو آھي. جيڪڏهن تصويرون ساڳيون آهن، ٻئي ڪارڊ ڪارڊ ۾ شامل ڪيا ويا آهن ڏيکاريل آهن ۽ سامهون رهنديون آهن. جيڪڏهن مختلف، ڪارڊ ڇڏيا ڪارڊ ڏيکاريا ويا آهن ۽ ٻنهي کي منهن ڏيڻو پوندو.

ميموري گيم هائيڊ ڪارڊ

جيڪڏهن ڪارڊ نه ملندا آهن، اهو طريقو سڏيو ويندو آهي ۽ ڪارڊ تصويرون لڪيل آهن.

ڏيکاريل = ڪوڙو.

ميموري گيم ڊيڊ اينڊ

جڏهن هن طريقي کي سڏيو ويندو آهي، ان جو مطلب آهي ته سڀئي ڪارڊ اڳ ۾ ئي ظاهر ڪيا ويا آهن ۽ ڪارڊ ڏيکاريل فهرست ۾ آهن: cardsShown.count = cards.count، تنهنڪري راند ختم ٿي وئي آهي. اهو طريقو خاص طور تي سڏيو ويندو آهي جڏهن اسان سڏيو آهي endGame() isPlaying var کي غلط تي سيٽ ڪرڻ لاءِ، جنهن کان پوءِ راند جو آخري پيغام ڏيکاريو ويو آهي. پڻ 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 سفارش ڪري ٿو:

جو ذريعو: www.habr.com

تبصرو شامل ڪريو