二十一点中牌的总价值

发布于 2025-01-12 15:44:57 字数 1906 浏览 0 评论 0原文

我正在编写一个二十一点纸牌游戏,试图慢慢让自己回到 Swift。

我正在尝试获取玩家手中的牌的总价值。

我遇到的问题是,当我遇到一个可以是 1 或 11 的 ace 时,我不确定在对其进行 XCTest 时如何解释这一点。

// Card model
struct Card {
    
    // Suit enumerated
    enum Suit : Character {
        case spades = "♠", hearts = "♡", diamonds = "♢", clubs = "♣"
    }
    
    // Rank enumerated
    enum Rank : Int {
        case two = 2, three, four, five, six, seven, eight, nine, ten
        case jack, queen, king, ace
                    
        struct Values {
            let first: Int, second : Int?
        }
        
        var values: Values {
            switch self {
            case .ace:
                return Values(first: 1, second: 11)
            case .jack, .queen, .king:
                return Values(first: 10, second: nil)
            default:
                return Values(first: self.rawValue, second: nil)
            }
        }
    }
    
    let rank: Rank, suit : Suit
    
    var value : Rank.Values {
        return self.rank.values
    }
}

当我来测试它时,

// XCTest
func testSumOfCardsEquals21() {
    let card1 = Card(rank: .jack, suit: .diamonds) //10
    let card2 = Card(rank: .four, suit: .diamonds) //4
    let card3 = Card(rank: .three, suit: .diamonds) //3
    let card4 = Card(rank: .ace, suit: .diamonds) //1 or 11
    
    let hand = [card1, card2, card3, card4]
    
    var total = 0
    for card in hand {
        let values = card.value
        if (values.second == nil) {
            total += values.first
        } else {
            let secondValue = values.second!
            total += secondValue
        }
    }
    
    // expected 21
    XCTAssertEqual(total, 21) // this will fail and return 28
}

在这种情况下,你希望 A 的值较低。

在您可能只有一张牌(A)的情况下,您希望它很高。

我不知道如何解决这样的测试要求。

...

为了澄清,当一张牌可以有两个值时,如何制作一个函数,测试计算手牌的总价值以返回预期的 21 总价值?

我感谢您的帮助和时间。

I'm coding up a blackjack card game to try to slowly get myself back into Swift.

I am trying to get a total value of the cards in a player's hand.

The problem I have is when I come to an ace which can be either 1 or 11, and I'm not sure how to account for this when I do a XCTest against it.

// Card model
struct Card {
    
    // Suit enumerated
    enum Suit : Character {
        case spades = "♠", hearts = "♡", diamonds = "♢", clubs = "♣"
    }
    
    // Rank enumerated
    enum Rank : Int {
        case two = 2, three, four, five, six, seven, eight, nine, ten
        case jack, queen, king, ace
                    
        struct Values {
            let first: Int, second : Int?
        }
        
        var values: Values {
            switch self {
            case .ace:
                return Values(first: 1, second: 11)
            case .jack, .queen, .king:
                return Values(first: 10, second: nil)
            default:
                return Values(first: self.rawValue, second: nil)
            }
        }
    }
    
    let rank: Rank, suit : Suit
    
    var value : Rank.Values {
        return self.rank.values
    }
}

When I come to test it,

// XCTest
func testSumOfCardsEquals21() {
    let card1 = Card(rank: .jack, suit: .diamonds) //10
    let card2 = Card(rank: .four, suit: .diamonds) //4
    let card3 = Card(rank: .three, suit: .diamonds) //3
    let card4 = Card(rank: .ace, suit: .diamonds) //1 or 11
    
    let hand = [card1, card2, card3, card4]
    
    var total = 0
    for card in hand {
        let values = card.value
        if (values.second == nil) {
            total += values.first
        } else {
            let secondValue = values.second!
            total += secondValue
        }
    }
    
    // expected 21
    XCTAssertEqual(total, 21) // this will fail and return 28
}

In this scenario you want the ace to be low.

In a scenario where you might just have 1 card (ace) you want it to be high.

I'm not sure how to resolve such a test requirement.

...

To clarify, how do you make a function, test to calculate the total value of the hand of cards to return the expected 21 total when a card can be two values?

I appreciate your help and time.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我是有多爱你 2025-01-19 15:44:57

那手牌的点数是 18,而不是 21。

Values 类型可能没有用——这些牌实际上没有原始值。

如果不先收集所有卡片,您就无法知道如何计算分数。

enum Rank: CaseIterable {
  case two, three, four, five, six, seven, eight, nine, ten
  case jack, queen, king
  case ace
}
struct Hand {
  init<Cards: Sequence>(cards: Cards) where Cards.Element == Card {
    let reduction = cards.reduce(into: (score: 0, aceCount: 0)) {
      switch $1.rank {
      case .jack, .queen, .king:
        $0.score += 10
      case .ace:
        $0.score += 1
        $0.aceCount += 1
      default:
        $0.score += try! $1.rank.caseIndex + 2
      }
    }

    var score = reduction.score
    reduction.aceCount.iterations
      .prefix { score <= 12 }
      .forEach { score += 9 }
    self.score = score
  }

  let score: Int
}
Hand(cards: [card1, card2, card3, card4]).score

public extension ExpressibleByIntegerLiteral where Self: Strideable, Stride: SignedInteger {
  /// *This many* iterations that produce no values.
  var iterations: LazyMapSequence<Range<Self>, Void> {
    (0..<self).lazy.map { _ in }
  }
}
public extension CaseIterable where Self: Equatable {
  /// The first match for this case in `allCases`.
  /// - Throws: `AllCasesError<Self>.noIndex`
  var caseIndex: AllCases.Index {
    get throws {
      do { return try Self.allCases.firstIndex(of: self).unwrapped }
      catch { throw AllCasesError.noIndex(self) }
    }
  }
}

public enum AllCasesError<Case: CaseIterable>: Error {
  /// No `AllCases.Index` corresponds to this case.
  case noIndex(Case)
}
public extension Optional {
  /// Represents that an `Optional` was `nil`.
  enum UnwrapError: Error {
    case `nil`
    case typeMismatch
  }

  /// [An alterative to overloading `??` to throw errors upon `nil`.](
  /// https://forums.swift.org/t/unwrap-or-throw-make-the-safe-choice-easier/14453/7)
  /// - Note: Useful for emulating `break`, with `map`, `forEach`, etc.
  /// - Throws: `UnwrapError` when `nil`.
  var unwrapped: Wrapped {
    get throws {
      switch self {
      case let wrapped?:
        return wrapped
      case nil:
        throw UnwrapError.nil
      }
    }
  }
}

That hand makes 18, not 21.

The Values type may not be useful—these cards don't really have raw values.

You can't know how to calculate the score without accumulating all of the cards first.

enum Rank: CaseIterable {
  case two, three, four, five, six, seven, eight, nine, ten
  case jack, queen, king
  case ace
}
struct Hand {
  init<Cards: Sequence>(cards: Cards) where Cards.Element == Card {
    let reduction = cards.reduce(into: (score: 0, aceCount: 0)) {
      switch $1.rank {
      case .jack, .queen, .king:
        $0.score += 10
      case .ace:
        $0.score += 1
        $0.aceCount += 1
      default:
        $0.score += try! $1.rank.caseIndex + 2
      }
    }

    var score = reduction.score
    reduction.aceCount.iterations
      .prefix { score <= 12 }
      .forEach { score += 9 }
    self.score = score
  }

  let score: Int
}
Hand(cards: [card1, card2, card3, card4]).score

public extension ExpressibleByIntegerLiteral where Self: Strideable, Stride: SignedInteger {
  /// *This many* iterations that produce no values.
  var iterations: LazyMapSequence<Range<Self>, Void> {
    (0..<self).lazy.map { _ in }
  }
}
public extension CaseIterable where Self: Equatable {
  /// The first match for this case in `allCases`.
  /// - Throws: `AllCasesError<Self>.noIndex`
  var caseIndex: AllCases.Index {
    get throws {
      do { return try Self.allCases.firstIndex(of: self).unwrapped }
      catch { throw AllCasesError.noIndex(self) }
    }
  }
}

public enum AllCasesError<Case: CaseIterable>: Error {
  /// No `AllCases.Index` corresponds to this case.
  case noIndex(Case)
}
public extension Optional {
  /// Represents that an `Optional` was `nil`.
  enum UnwrapError: Error {
    case `nil`
    case typeMismatch
  }

  /// [An alterative to overloading `??` to throw errors upon `nil`.](
  /// https://forums.swift.org/t/unwrap-or-throw-make-the-safe-choice-easier/14453/7)
  /// - Note: Useful for emulating `break`, with `map`, `forEach`, etc.
  /// - Throws: `UnwrapError` when `nil`.
  var unwrapped: Wrapped {
    get throws {
      switch self {
      case let wrapped?:
        return wrapped
      case nil:
        throw UnwrapError.nil
      }
    }
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文