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

SwiftUI开发Set游戏:如何重构有效牌组校验重复代码

Set卡牌游戏有效牌组通用校验实现方案

你不需要为形状、颜色、数量、填充样式四类特征分别写结构完全重复的校验函数,用Swift原生的KeyPath+泛型就能实现一套逻辑覆盖所有特征校验,完全不需要硬编码枚举分支、也不需要给不同特征单独写计数逻辑。


核心实现思路

Set游戏的单特征校验规则非常统一:三张牌的同一个特征要么完全相同,要么完全不同,不需要针对具体枚举case做计数。通过泛型约束保证传入的特征类型支持相等判断,再通过KeyPath指定要读取的Card属性,就能解决你遇到的「传入不同特征类型访问对应属性」的问题。

具体代码实现

首先写单特征通用校验函数:

/// 单特征有效性校验
/// - Parameters:
///   - cards: 待校验的三张牌
///   - feature: Card结构体对应特征的KeyPath,支持所有遵守Equatable协议的属性类型
private func isFeatureValid<T: Equatable>(for cards: [Card], feature: KeyPath<Card, T>) -> Bool {
    // 有效牌组固定为3张,数量不对直接返回false
    guard cards.count == 3 else { return false }
    
    // 通过KeyPath读取三张牌对应特征的值
    let first = cards[0][keyPath: feature]
    let second = cards[1][keyPath: feature]
    let third = cards[2][keyPath: feature]
    
    // 判断是否满足「全相同」或「全不同」规则
    let allEqual = (first == second) && (second == third)
    let allDistinct = (first != second) && (second != third) && (first != third)
    
    return allEqual || allDistinct
}

基于这个通用函数,整组牌的有效性判断只需要依次校验四个特征即可:

/// 判断选中的三张牌是否为有效Set牌组
func isSelectedCardsValid(cards: [Card]) -> Bool {
    guard cards.count == 3 else { return false }
    return isFeatureValid(for: cards, feature: \.color)
        && isFeatureValid(for: cards, feature: \.shape)
        && isFeatureValid(for: cards, feature: \.filling)
        && isFeatureValid(for: cards, feature: \.number)
}

方案优势

  • 完全消除重复代码:不需要为每个特征单独写计数、switch分支逻辑,代码量缩减80%以上
  • 避免低级错误:不会出现你原有代码里「匹配紫色case时给blue计数变量+1」这类笔误
  • 扩展性极强:后续如果要给Card新增其他校验特征,只要属性遵守Equatable协议,直接传入对应KeyPath即可复用整套校验逻辑,不需要修改核心校验代码

内容的提问来源于stack exchange,提问作者Real Analysis Noob

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 06:36:24