سوئفٹ میں میموری کارڈ گیم لکھنا

سوئفٹ میں میموری کارڈ گیم لکھنا

یہ مضمون ایک سادہ میموری ٹریننگ گیم بنانے کے عمل کو بیان کرتا ہے جو مجھے واقعی پسند ہے۔ اپنے آپ میں اچھے ہونے کے علاوہ، آپ جاتے جاتے سوئفٹ کلاسز اور پروٹوکولز کے بارے میں کچھ اور سیکھیں گے۔ لیکن اس سے پہلے کہ ہم شروع کریں، آئیے خود کھیل کو سمجھیں۔

ہم آپ کو یاد دلاتے ہیں: "Habr" کے تمام قارئین کے لیے - "Habr" پروموشنل کوڈ کا استعمال کرتے ہوئے کسی بھی Skillbox کورس میں داخلہ لینے پر 10 rubles کی رعایت۔

Skillbox تجویز کرتا ہے: تعلیمی آن لائن کورس "پیشہ جاوا ڈویلپر".

میموری کارڈ کیسے کھیلا جائے۔

کھیل تاش کے ایک سیٹ کے مظاہرے سے شروع ہوتا ہے۔ وہ منہ کے بل لیٹتے ہیں (بالترتیب، تصویر نیچے)۔ جب آپ کسی ایک پر کلک کرتے ہیں تو تصویر چند سیکنڈ کے لیے کھل جاتی ہے۔

کھلاڑی کا کام ایک ہی تصویر والے تمام کارڈز تلاش کرنا ہے۔ اگر، پہلا کارڈ کھولنے کے بعد، آپ دوسرا پلٹ دیتے ہیں اور تصویریں ملتی ہیں، تو دونوں کارڈ کھلے رہتے ہیں۔ اگر وہ میچ نہیں کرتے ہیں تو، کارڈ دوبارہ بند کر دیا جاتا ہے. مقصد ہر چیز کو کھولنا ہے۔

پروجیکٹ کا ڈھانچہ

اس گیم کا سادہ ورژن بنانے کے لیے آپ کو درج ذیل اجزاء کی ضرورت ہے:

  • ایک کنٹرولر: GameController.swift۔
  • ایک منظر: CardCell.swift۔
  • دو ماڈلز: MemoryGame.swift اور Card.swift۔
  • Main.storyboard یقینی بنانے کے لیے کہ اجزاء کا پورا سیٹ دستیاب ہے۔

ہم کھیل کے سب سے آسان جزو، کارڈز سے شروع کرتے ہیں۔

کارڈ سوئفٹ

کارڈ ماڈل میں تین خصوصیات ہوں گی: ہر ایک کی شناخت کے لیے id، کارڈ کی حیثیت (پوشیدہ یا کھلا) بتانے کے لیے دکھایا گیا ایک بولین متغیر، اور کارڈز پر موجود تصاویر کے لیے آرٹ ورک یو آر ایل۔

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
}

یہ طریقہ **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 نامی اسٹوری بورڈ میں دیکھ سکتے ہیں۔

کنٹرولرز کے نفاذ کے بارے میں تھوڑا سا:

  • سب سے پہلے، ہم دو اہم اشیاء کو شروع کرتے ہیں - گرڈ: گیم = میموری گیم ()، اور کارڈز کا ایک سیٹ: کارڈز = [کارڈ] ()۔
  • ہم ابتدائی متغیرات کو viewDidLoad کے طور پر سیٹ کرتے ہیں، یہ پہلا طریقہ ہے جسے گیم کے چلنے کے دوران کہا جاتا ہے۔
  • کلیکشن ویو کو پوشیدہ پر سیٹ کیا گیا ہے کیونکہ تمام کارڈز اس وقت تک چھپے رہتے ہیں جب تک صارف پلے کو دباتا ہے۔
  • جیسے ہی ہم 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۔

تمام چار طریقوں کو مرکزی کلاس کے لیے لاگو کیا جا سکتا ہے، جو گیم کنٹرولر ہے۔

میموری گیم ڈڈ اسٹارٹ

جب یہ طریقہ چلایا جاتا ہے تو گیم شروع ہو جانا چاہیے (صارف پلے کو دباتا ہے)۔ یہاں ہم collectionView.reloadData() پر کال کرکے مواد کو دوبارہ لوڈ کریں گے، جو کارڈز کو بدل دے گا۔

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

میموری گیم شو کارڈز

ہم اس طریقہ کو collectionSDViewSelectItemAt سے کہتے ہیں۔ پہلے یہ منتخب کارڈ دکھاتا ہے۔ پھر یہ دیکھنے کے لیے چیک کرتا ہے کہ آیا کارڈز دکھائے گئے سرنی میں کوئی بے مثال کارڈ موجود ہے (اگر دکھائے گئے کارڈز کی تعداد طاق ہے)۔ اگر ایک ہے، تو منتخب کارڈ کا موازنہ اس سے کیا جاتا ہے۔ اگر تصویریں ایک جیسی ہیں، تو دونوں کارڈز دکھائے گئے کارڈز میں شامل کیے جاتے ہیں اور سامنے رہتے ہیں۔ اگر مختلف ہو تو، کارڈ چھوڑتا ہے کارڈ دکھائے جاتے ہیں اور دونوں کو منہ کی کھانی پڑتی ہے۔

میموری گیم ہائیڈ کارڈز

اگر کارڈز مماثل نہیں ہیں، تو اس طریقہ کو بلایا جاتا ہے اور کارڈ کی تصاویر چھپائی جاتی ہیں۔

دکھایا = غلط۔

میموری گیم ڈائیڈ اینڈ

جب یہ طریقہ کہا جاتا ہے، تو اس کا مطلب ہے کہ تمام کارڈز پہلے ہی ظاہر ہو چکے ہیں اور کارڈز کی دکھائی گئی فہرست میں ہیں: cardsShown.count = cards.count، اس لیے گیم ختم ہو گئی۔ طریقہ کو خاص طور پر اس وقت کہا جاتا ہے جب ہم نے isPlaying var کو غلط پر سیٹ کرنے کے لیے endGame() کو کال کیا، جس کے بعد گیم کا اختتامی پیغام دکھایا جاتا ہے۔ نیز alertController کو کنٹرولر کے اشارے کے طور پر استعمال کیا جاتا ہے۔ 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

نیا تبصرہ شامل کریں