2017-01-13 66 views
1

爲了好玩,我在Swift中從零開始構建一個FreeCell紙牌遊戲。我已經有了用於構建甲板的套牌模型,並且每個卡牌結構都有套裝,等級和描述(例如4♠️)以及其他一些屬性。遊戲模型只是存儲哪些卡在哪些列。視圖中的變化(移動卡片)將提醒控制器修改哪些卡片在哪些列中。在視圖與模型之間溝通「哪張牌」 - 最佳方式?

當用戶點擊卡片時(UIView的一個子類包括一個包含card.description的標籤),label.text將被髮送給控制器來識別模型中的卡片。我想知道做這件事的最好方法是什麼。

我能想到的最明顯的方法是構建字典,其中的鍵是描述,值是卡片。當然,我可以在我的DeckBuilder類中編寫一個函數爲我構建字典。但是由於描述已經作爲Card結構的一個屬性存在,這看起來有點多餘且笨拙。

另一種方法是,每次選擇一張卡時,遍歷模型中的一副牌,並說「如果selectedCard.description == tryCard.description {//這是合適的牌!}」但是這似乎荒謬不雅,理論上計算過於昂貴(儘管實際上我相信它不會花時間)。

我想做的事情就是讓控制器說「得到具有此字符串作爲其描述屬性的卡」。與字典查找類似,但沒有實際字典。

這是最後的解決方案嗎?如果不是,你認爲最好的是什麼?

Thankya!

回答

1

您不應該在某個位置使用標籤的文本作爲值的指示;這就像在你的視圖中存儲你的模型。相反,你已經到了代表列狀態的內部結構。每列可以是一個卡片陣列。列本身可以是一列列:

struct Card {} 
    var deck = [Card]() 
    var columns: [[Card]] = [[Card]](repeating: [], count: 7) 
    deck.shuffle() 
    for i in 0..<columns.count { 
     for j in 0..<i { 
      columns[i].append(deck.draw()) 
     } 
    } 

現在,如果您有一個點擊一個視圖。您只需要知道該列中的哪個列和哪個索引被點擊過(您可以根據視圖的框架或通過爲每個視圖分配一個標籤來完成此操作)。你現在可以獲得卡的價值,但看着列數組:列[selectedColumn] [selectedRow]

+0

謝謝!這似乎是模型和視圖之間更好的溝通方式。 –

1

我會創建兩個枚舉,一個爲排名和一個爲西裝。

enum Rank { 
    case value(Int) 
    case jack 
    case queen 
    case king 
    case ace 
} 

enum Suit { 
    case diamond 
    case heart 
    case spade 
    case club 
} 

這比字典更安全,更可讀。在你的結構卡中,你可以添加這兩個屬性。

struct Card { 
    var rank: Rank 
    var suit: Suit 
} 

如果您想要比較字符串,比較枚舉或者甚至讓您的卡片結構符合Equatable協議,這取決於您。我可能會選擇Equatable協議,但我不認爲這些選項之間存在很大差異。