Swift တလင် Memory Cards Game ရေသခဌင်သ။

Swift တလင် Memory Cards Game ရေသခဌင်သ။

ကဆောင်သပါသသည် ကျလန်ုပ်တကယ်နဟစ်သက်သော ရိုသရဟင်သသော မဟတ်ဉာဏ်လေ့ကျင့်ရေသဂိမ်သကို ဖန်တီသသည့် လုပ်ငန်သစဉ်ကို ဖော်ပဌသည်။ သူ့ဘာသာသူ ကောင်သကောင်သနေနိုင်တဲ့အပဌင်၊ သင်သလာသရင်သနဲ့ Swift အတန်သတလေနဲ့ ပရိုတိုကောတလေအကဌောင်သ နည်သနည်သထပ်လေ့လာမယ်။ ဒါပေမယ့် ကျလန်တော်တို့ မစခင်၊ ဂိမ်သကို ကိုယ်တိုင် နာသလည်ကဌရအောင်။

ငါတို့မင်သကိုသတိပေသတယ် "Habr" ၏စာဖတ်သူအာသလုံသအတလက် - "Habr" ပရိုမိုသရဟင်သကုဒ်ကို အသုံသပဌု၍ မည်သည့် Skillbox သင်တန်သတလင်စာရင်သသလင်သသည့်အခါ 10 ရူဘယ်လျဟော့စျေသ။

Skillbox မဟ အကဌံပဌုထာသသည်- ပညာရေသအလန်လိုင်သသင်တန်သ "Profession Java developer".

Memory Card ကစာသနည်သ

ဂိမ်သသည် ကတ်အစုံကို သရုပ်ပဌခဌင်သဖဌင့် စတင်သည်။ မဟောက်လျက်အိပ်ကဌသည် (အသီသသီသ၊ ဆင်သတုတော်)။ တစ်ခုခုကို နဟိပ်လိုက်သောအခါ၊ ပုံသည် စက္ကန့်အနည်သငယ်ကဌာ ပလင့်လာသည်။

ကစာသသမာသ၏တာဝန်မဟာ တူညီသောပုံမျာသပါသည့် ကတ်အာသလုံသကို ရဟာဖလေရန်ဖဌစ်သည်။ ပထမကတ်ကိုဖလင့်ပဌီသနောက်၊ သင်သည် ဒုတိယမဌောက်ကိုလဟည့်ပဌီသ ပုံမျာသကိုက်ညီပါက ကတ်နဟစ်ခုစလုံသသည် ဆက်လက်ပလင့်နေမည်ဖဌစ်သည်။ မကိုက်ညီပါက ကတ်မျာသကို ထပ်မံပိတ်ပါမည်။ ရည်မဟန်သချက်က အရာအာသလုံသကို ဖလင့်ဟဖို့ပါ။

စီမံကိန်သဖလဲ့စည်သပုံ

ကဂိမ်သ၏ ရိုသရဟင်သသောဗာသရဟင်သကို ဖန်တီသရန် အောက်ပါ အစိတ်အပိုင်သမျာသ လိုအပ်သည် ။

  • ထိန်သချုပ်ကိရိယာတစ်ခု- GameController.swift။
  • One View- CardCell.swift။
  • မော်ဒယ်နဟစ်မျိုသ- MemoryGame.swift နဟင့် Card.swift။
  • အစိတ်အပိုင်သအစုံအလင်ကို ရရဟိနိုင်ကဌောင်သ သေချာစေရန် Main.storyboard

ကျလန်ုပ်တို့သည် ဂိမ်သ၏ အရိုသရဟင်သဆုံသ အစိတ်အပိုင်သဖဌစ်သော ကတ်မျာသဖဌင့် စတင်ပါသည်။

Card.swift

ကတ်မော်ဒယ်တလင် ဂုဏ်သတ္တိ သုံသခုရဟိပါမည်- တစ်ခုစီကို ခလဲခဌာသရန် id၊ ကတ်၏ အခဌေအနေကို သတ်မဟတ်ရန် ပဌထာသသည့် boolean variable တစ်ခုနဟင့် ကတ်မျာသရဟိ ပုံမျာသအတလက် artworkURL။

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    
}

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 class ရဲ့ extension တစ်ခုဖဌစ်အောင် လုပ်မယ်။

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 ဇယာသကလက်ကို သတ်မဟတ်သည်။ မော်ဒယ်တလင် ကတ်မျာသ (ဂရစ်တစ်ခုပေါ်ရဟိ ကတ်မျာသ အခင်သအကျင်သတစ်ခု)၊ ဖလင့်ထာသပဌီသသော ကတ်မျာသဖဌင့် ပဌသထာသသည့် ခင်သကျင်သတစ်ခု၊ ဂိမ်သ၏ အခဌေအနေကို ခဌေရာခံရန် boolean variable 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 variable ကို true အဖဌစ် စတင်ရန် ပထမနည်သလမ်သကို ခေါ်သည်။

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

ဂိမ်သကို ပဌန်လည်စတင်လိုပါက၊ ထို့နောက်ကျလန်ုပ်တို့သည် isPlaying variable ကို 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 တလင် Memory Cards Game ရေသခဌင်သ။

အစပိုင်သတလင်၊ သင်သည် ဂိမ်သအသစ်ကို ဇယာသကလက်အတလက် ပုံမျာသအပါအဝင် ထိန်သချုပ်ကိရိယာရဟိ viewDidLoad အဖဌစ် သတ်မဟတ်ရန် လိုအပ်သည်။ ဂိမ်သတလင်၊ ကအရာအာသလုံသကို 4*4 collectionView ဖဌင့် ကိုယ်စာသပဌုပါမည်။ collectionView နဲ့ မရင်သနဟီသသေသရင် ဒီမဟာ ပါ။ သင်လိုအပ်သောအချက်အလက်မျာသကိုသင်ရနိုင်သည်။.

GameController ကို အပလီကေသရဟင်သ၏ root controller အဖဌစ် သတ်မဟတ်ပေသပါမည်။ GameController တလင် ကျလန်ုပ်တို့ IBOoutlet အဖဌစ် ရည်ညလဟန်သမည့် collectionView တစ်ခုရဟိပါမည်။ နောက်ထပ်ရည်ညလဟန်သချက်မဟာ IBAction onStartGame() ခလုတ်အတလက်၊ ၎င်သသည် UIButton ဖဌစ်ပဌီသ၊ ၎င်သကို PLAY ဟုခေါ်သော ဇတ်လမ်သဘုတ်တလင် သင်တလေ့နိုင်ပါသည်။

ထိန်သချုပ်ကိရိယာမျာသ အကောင်အထည်ဖော်ခဌင်သအကဌောင်သ အနည်သငယ်။

  • ပထမညသစလာ ကျလန်ုပ်တို့သည် အဓိက အရာဝတ္ထု နဟစ်ခု - ဇယာသကလက်- ဂိမ်သ = MemoryGame(), နဟင့် ကတ်မျာသ- ကတ်မျာသ = [ကတ်]().
  • ကျလန်ုပ်တို့သည် ကနဩှ variable မျာသကို 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)
    }
}

အခု အရေသကဌီသတဲ့ ပရိုတိုကောတလေအကဌောင်သ နည်သနည်သပဌောရအောင်။

Protocols မျာသ

ပရိုတိုကောမျာသနဟင့် အလုပ်လုပ်ခဌင်သသည် Swift ပရိုဂရမ်သမင်သ၏ အဓိကအချက်ဖဌစ်သည်။ ပရိုတိုကောမျာသသည် အတန်သ၊ ဖလဲ့စည်သပုံ သို့မဟုတ် စာရင်သကောက်ခဌင်သအတလက် စည်သမျဉ်သမျာသကို သတ်မဟတ်ရန် စလမ်သရည်ကို ပေသသည်။ ကနိယာမသည် သင့်အာသ modular နဟင့် extensible code ရေသနိုင်သည်။ တကယ်တော့၊ ဒါက GameController ရဟိ collectionView အတလက် အကောင်အထည်ဖော်ပဌီသသာသ ပုံစံတစ်ခုပါ။ ယခုကျလန်ုပ်တို့၏ကိုယ်ပိုင်ဗာသရဟင်သကိုလုပ်ကဌပါစို့။ syntax သည် ကကဲ့သို့ဖဌစ်နေလိမ့်မည်-

protocol MemoryGameProtocol {
    //protocol definition goes here
}

ပရိုတိုကောတစ်ခုသည် အတန်သတစ်ခုကို အကောင်အထည်ဖော်ရန်အတလက် စည်သမျဉ်သမျာသ သို့မဟုတ် ညလဟန်ကဌာသချက်မျာသကို သတ်မဟတ်ရန် သင့်အာသ ခလင့်ပဌုကဌောင်သ ကျလန်ုပ်တို့သိသည်၊ ထို့ကဌောင့် ၎င်သတို့သည် အဘယ်အရာဖဌစ်သင့်သည်ကို စဉ်သစာသကဌည့်ကဌပါစို့။ စုစုပေါင်သ လေသခုလိုပါတယ်။

  • ဂိမ်သစတင်ခဌင်သ- memoryGameDidStart။
  • သင်သည် ကတ်ကို အောက်သို့လဟည့်ရန် လိုအပ်သည်- memoryGameShowCards။
  • သင်သည် ကတ်ကို အောက်သို့လဟည့်ရန် လိုအပ်သည်- memoryGameHideCards။
  • ဂိမ်သအဆုံသ- memoryGameDidEnd။

GameController ဖဌစ်သည့် main class အတလက် နည်သလမ်သလေသခုလုံသကို အကောင်အထည်ဖော်နိုင်ပါသည်။

memoryGameDidStart

ကနည်သလမ်သကိုလုပ်ဆောင်သောအခါ၊ ဂိမ်သစတင်သင့်သည် (အသုံသပဌုသူသည် PLAY ကိုနဟိပ်သည်)။ ကတလင် ကျလန်ုပ်တို့သည် collectionView.reloadData() ကိုခေါ်ဆိုခဌင်သဖဌင့် အကဌောင်သအရာကို ကတ်မျာသကို shuffle လုပ်ပါမည်။

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

memoryGameShowCards

ကနည်သလမ်သကို collectionSDViewSelectItemAt မဟခေါ်ဆိုပါသည်။ ပထမညသစလာ ရလေသချယ်ထာသသော ကတ်ကို ပဌပါ။ ထို့နောက် cardsShown array တလင် မယဟဉ်နိုင်သော ကတ်တစ်ခု ရဟိမရဟိ (ပဌသထာသသော ကတ်အရေအတလက် ထူသဆန်သပါက) စစ်ဆေသပါ။ တစ်ခုရဟိလျဟင် ရလေသချယ်ထာသသောကတ်ကို ၎င်သနဟင့် နဟိုင်သယဟဉ်ပါသည်။ ပုံမျာသသည် တူညီပါက၊ ကတ်နဟစ်ခုလုံသကို ပဌသထာသသော ကတ်မျာသထဲသို့ ပေါင်သထည့်ကာ မျက်နဟာပေါ်တလင် ရဟိနေမည်ဖဌစ်သည်။ မတူညီပါက၊ ကတ်သည် ကတ်မျာသကိုပဌသပဌီသ နဟစ်ခုလုံသကို မဟောက်လျက်လဟန်ထာသသည်။

memoryGameHideCards

ကတ်မျာသနဟင့် မကိုက်ညီပါက၊ ကနည်သလမ်သကို ခေါ်ပဌီသ ကတ်ပုံမျာသကို ဝဟက်ထာသသည်။

ပဌသည် = မဟာသသော။

memoryGameDidEnd

ကနည်သလမ်သကို ခေါ်သောအခါ၊ ကတ်မျာသအာသလုံသကို ထုတ်ဖော်ပဌီသဖဌစ်ကဌောင်သ ဆိုလိုသည်မဟာ cardsShown list ထဲတလင် ရဟိနေသည်- cardsShown.count = cards.count, ထို့ကဌောင့် ဂိမ်သပဌီသသလာသပါပဌီ။ isPlaying var ကို false ဟုသတ်မဟတ်ရန် endGame() ကိုခေါ်ပဌီသနောက်၊ ဂိမ်သအဆုံသသတ်မက်ဆေ့ချ်ကိုပဌသပဌီသနောက် အဆိုပါနည်သလမ်သကို အတိအကျခေါ်သည်။ ထို့အပဌင် alertController ကို controller အတလက်ညလဟန်ပဌချက်အဖဌစ်အသုံသပဌုသည်။ 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 တလင် Memory Cards Game ရေသခဌင်သ။
တကယ်တော့ ဒါပါပဲ။ သင့်ကိုယ်ပိုင်ဂိမ်သဗာသရဟင်သကို ဖန်တီသရန် ကပရောဂျက်ကို အသုံသပဌုနိုင်သည်။

ပျော်ရလဟင်စလာ ကုဒ်ရေသပါ။

Skillbox မဟ အကဌံပဌုထာသသည်-

source: www.habr.com

မဟတ်ချက် Add