我正在嘗試用 Swift 創建一個紙牌游戲。我的模型是一個名為 SetGame 的結構,它包含一個結構 Card 型別的卡片陣列,其中 Card 中的一個變數是另一個名為 content 的結構,它是我在視圖模型中設定為一個名為 SetCard 的結構的 CardContent 型別。它具有以下變數:顏色、陰影、numberOfShapes 和形狀。
我似乎無法弄清楚如何訪問我的模型中的 cardContent 變數,例如形狀和顏色。
當我輸入 print(card1.content.shape) 時,我收到一條錯誤訊息,指出“‘CardContent’型別的值沒有成員‘shape’”
當我列印 (card1) 時,我得到“Card(isSelected: true, isMatched: false, content: Set.SetCard(color: Purple, numberOfShapes: 1, shape: "Diamond", shading: 0.1), id: 54)”
當我列印(card1.content)時,我得到了我正在尋找的值“SetCard(顏色:紫色,numberOfShapes:1,形狀:“鉆石”,陰影:0.1)”
如何訪問這些值?
struct SetGame<CardContent> where CardContent: Equatable {
private(set) var cards: Array<Card>
private(set) var dealtCards: Array<Card>
private(set) var score = 0
private(set) var selectedCards = [Int]()
init(numberOfPairOfCards: Int, creatrCardContent: (Int) -> CardContent) {
cards = []
dealtCards = [Card]()
for pairIndex in 0..<numberOfPairOfCards {
let content: CardContent = creatrCardContent(pairIndex)
cards.append(Card(content: content, id: pairIndex))
}
cards.shuffle()
for _ in 0..<12{
if let dealtCard = cards.popLast(){
self.dealtCards.append(dealtCard)
}
}
}
mutating func choose(_ card: Card){
if let chosenIndex = dealtCards.firstIndex(where: {$0.id == card.id}) {
if !dealtCards[chosenIndex].isSelected {
selectedCards.append(dealtCards[chosenIndex].id)
} else {
selectedCards.removeLast()
}
dealtCards[chosenIndex].isSelected = !dealtCards[chosenIndex].isSelected
print(selectedCards)
}
if selectedCards.count == 3 {
print("Let's see if they match")
print(doesMatch(cards: selectedCards))
}
}
func doesMatch(cards: [Int]) -> Bool {
// Get card content from id in cards array
if let card1 = dealtCards.first(where: { $0.id == cards[0]}) {
print(card1)
print(card1.content)
print(card1.content.shape)
}
return false
}
struct Card: Identifiable {
var isSelected = false
var isMatched = false
let content: CardContent
let id : Int
}
}
struct SetCard : Equatable {
let color : Color
let numberOfShapes: Int
let shape : String
let shading : Double
}
class SetGameViewModel: ObservableObject {
typealias Card = SetGame<SetCard>.Card
@Published private var model: SetGame<SetCard>
init() {
self.model = SetGameViewModel.createGame()
}
var cards: Array<Card> {
return model.cards
}
var dealtCards: Array<Card> {
return model.dealtCards
}
static func createGame() -> SetGame<SetCard> {
var cardDeck : [SetCard] = []
let shapes = ["Diamond", "Squiggle", "Oval"]
let colors = [Color.red, Color.green, Color.purple]
let counts = [1,2,3]
let shades = [0.1, 0.5, 1]
for color in colors {
for shape in shapes {
for count in counts {
for shade in shades {
let card = SetCard.init(color: color, numberOfShapes: count, shape: shape, shading: shade)
cardDeck.append(card)
}
}
}
}
return SetGame<SetCard>(numberOfPairOfCards: cardDeck.count) {pairIndex in
cardDeck[pairIndex]
}
}
// Mark:= Intents(s)
func choose(_ card: Card){
model.choose(card)
}
}
uj5u.com熱心網友回復:
你做了content泛型,所以它的型別實際上是Equatable. 這意味著您需要將content轉換為其實際型別SetCard,現在您可以訪問其屬性:
if let card1 = dealtCards.first(where: { $0.id == cards[0]}) {
print(card1)
print(card1.content)
let content = card1.content as! SetCard
print(content.shape)
}
uj5u.com熱心網友回復:
您已經SetGame對卡片的內容進行了通用化,因此大概,您不希望您的游戲邏輯依賴于或假設這些卡片上的內容,對嗎?游戲應該適用于任何型別的卡片內容。
但是,在您的doesMatch方法中,您正試圖通過訪問卡片內容的屬性來做到這一點shape。您假設用于此游戲的任何卡片內容都有一個shape屬性。如果我使用這個Foo我剛剛組成的隨機結構作為卡片內容會怎樣?
struct Foo: Equatable {
let x: Int
}
沒有shape財產Foo,是嗎?這就是出現錯誤的原因。
從方法的名稱來看doesMatch,您實際上不需要訪問卡片的形狀或類似的東西。為什么不只是比較卡片內容的相等性,看看它們是否匹配?Equatable畢竟,你已經限制了他們。
if let card1 = dealtCards.first(where: { $0.id == cards[0]}),
let card2 = dealtCards.first(where: { $0.id == cards[1]}) {
let firstTwoCardsMatch = card1.content == card2.content
}
如果你有更復雜的匹配邏輯,你應該寫一個Matchable這樣的協議:
protocol Matchable {
func doesMatch(other: Self) -> Bool
}
struct SetGame<CardContent> where CardContent: Equatable & Matchable {
...
// in doesMatch, you can do:
let firstTwoCardsMatch = card1.content.doesMatch(other: card2.content)
}
// write your matching logic in SetCard
struct SetCard : Equatable, Matchable {
let color : Color
let numberOfShapes: Int
let shape : String
let shading : Double
func doesMatch(other: SetCard) -> Bool {
...
}
}
如果您shape出于某種原因非常想訪問那里的屬性,您可以引入一個具有shape屬性的新協議:
protocol CardContentWithShape {
var shape: String { get }
}
然后符合SetCard它:
struct SetCard : Equatable, CardContentWithShape {
并約束CardContent它:
struct SetGame<CardContent> where CardContent: Equatable & CardContentWithShape {
現在CardContent只能是既是Equatable and 的 東西CardContentWithShape,所以它必須有一個shape屬性,所以你將能夠做到:
print(card1.content.shape)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/399863.html
上一篇:操作無法完成。應用程式資訊提供程式(FBSApplicationLibrary)為“io.dopple.Dopple”回傳nil
下一篇:iOSFirebase按日期分頁
