You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于单个CardSubview类创建不同样式的iOS游戏卡片?

Hey there! Let's fix that issue with your Set-like iOS game where all cards are updating their styles together. The root problem here is using static properties (like your index1/index2/index3/index4) for your CardSubview—static values are shared across every instance of the class, so changing them updates every card at once. Here's how to refactor your code to get independent, unique card styles:


1. Replace Static Properties with Instance-Level Properties

First, ditch the static indices and give each CardSubview its own set of style properties. Instead of relying on class-wide values, define properties that belong to individual card instances. For clarity, use enums to represent your style options (this avoids magic numbers and makes your code more readable):

// Inside CardSubview.swift
class CardSubview: UIView {
    // Define enums for each style dimension (matches Set's game rules)
    enum CardShape { case square, triangle, circle }
    enum CardColor { case red, green, purple }
    enum CardFill { case solid, striped, outlined }
    
    // Instance properties: each card has its own unique values
    var shape: CardShape = .square
    var color: CardColor = .red
    var fill: CardFill = .solid
    var shapeCount: Int = 1 // 1, 2, or 3

    // ... rest of your view code (init, draw methods, etc.)
}

2. Initialize Each Card with Unique Style Data

In your CardBoardView, generate all 80 unique style combinations first, then create a CardSubview for each combination and pass in its specific style values.

First, create a helper struct to organize style data neatly:

struct CardStyle {
    let shape: CardSubview.CardShape
    let color: CardSubview.CardColor
    let fill: CardSubview.CardFill
    let count: Int
}

Then generate all possible unique styles (Set has 3^4 = 81 total styles—remove one to get 80):

// Inside CardBoardView.swift
func generateAllUniqueCardStyles() -> [CardStyle] {
    let shapes: [CardSubview.CardShape] = [.square, .triangle, .circle]
    let colors: [CardSubview.CardColor] = [.red, .green, .purple]
    let fills: [CardSubview.CardFill] = [.solid, .striped, .outlined]
    let counts = [1, 2, 3]
    
    var allStyles = [CardStyle]()
    
    // Generate every possible combination
    for shape in shapes {
        for color in colors {
            for fill in fills {
                for count in counts {
                    allStyles.append(CardStyle(shape: shape, color: color, fill: fill, count: count))
                }
            }
        }
    }
    
    // Remove one random style to get 80 unique cards
    if let randomIndex = allStyles.indices.randomElement() {
        allStyles.remove(at: randomIndex)
    }
    
    return allStyles
}

Now create and add each card to your board:

func setupCardBoard() {
    let uniqueStyles = generateAllUniqueCardStyles()
    
    for (index, style) in uniqueStyles.enumerated() {
        let card = CardSubview()
        // Assign the unique style to this card instance
        card.shape = style.shape
        card.color = style.color
        card.fill = style.fill
        card.shapeCount = style.count
        
        // Position the card (adjust layout logic to fit your board)
        let cardSize = CGSize(width: 80, height: 120)
        let x = (index % 8) * Int(cardSize.width) + 20
        let y = (index / 8) * Int(cardSize.height) + 20
        card.frame = CGRect(x: x, y: y, width: cardSize.width, height: cardSize.height)
        
        addSubview(card)
    }
}

3. Update Card Drawing Logic to Use Instance Properties

Modify your draw(_ rect: CGRect) method in CardSubview to use the instance properties instead of static indices. For example:

override func draw(_ rect: CGRect) {
    super.draw(rect)
    
    // Draw based on this card's unique properties
    switch shape {
    case .square:
        drawSquare(with: color, fillStyle: fill, count: shapeCount, in: rect)
    case .triangle:
        drawTriangle(with: color, fillStyle: fill, count: shapeCount, in: rect)
    case .circle:
        drawCircle(with: color, fillStyle: fill, count: shapeCount, in: rect)
    }
}

// Example helper method for drawing squares
private func drawSquare(with color: CardColor, fillStyle: CardFill, count: Int, in rect: CGRect) {
    // Convert enum values to actual UIColors/paths/fill logic
    let uiColor: UIColor = {
        switch color {
        case .red: return .red
        case .green: return .green
        case .purple: return .purple
        }
    }()
    
    // Draw 1, 2, or 3 squares with the correct fill style
    // ... your drawing implementation here
}

4. Bonus: Dynamically Update Individual Card Styles (If Needed)

If you ever need to change a single card's style later (e.g., for game mechanics), add a method to CardSubview to update its properties and trigger a redraw:

func updateStyle(with newStyle: CardStyle) {
    self.shape = newStyle.shape
    self.color = newStyle.color
    self.fill = newStyle.fill
    self.shapeCount = newStyle.count
    setNeedsDisplay() // Tells the view to redraw with the new style
}

With these changes, every CardSubview will have its own independent style. Creating 80 unique cards is as simple as generating the style combinations and passing them to each card instance, and modifying one card won't affect any others.

内容的提问来源于stack exchange,提问作者INFORMATIKER IM ALL

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:33:09