diff --git a/Blackjack/Blackjack/Engine/GameState.swift b/Blackjack/Blackjack/Engine/GameState.swift index 031683c..387aad9 100644 --- a/Blackjack/Blackjack/Engine/GameState.swift +++ b/Blackjack/Blackjack/Engine/GameState.swift @@ -77,6 +77,12 @@ final class GameState { /// Whether an action is currently being processed (prevents double-tap issues). private(set) var isProcessingAction: Bool = false + /// Time of the last player action (prevents rapid double-taps). + private var lastActionTime: Date = .distantPast + + /// Minimum interval between player actions in seconds. + private let actionDebounceInterval: TimeInterval = 0.2 + /// The active player hand. var activeHand: BlackjackHand? { guard activeHandIndex < playerHands.count else { return nil } @@ -598,6 +604,12 @@ final class GameState { /// Player hits (takes another card). func hit() async { guard canHit else { return } + + // Debounce: ignore rapid taps + let now = Date() + guard now.timeIntervalSince(lastActionTime) >= actionDebounceInterval else { return } + lastActionTime = now + isProcessingAction = true defer { isProcessingAction = false } @@ -619,6 +631,12 @@ final class GameState { /// Player stands. func stand() async { guard canStand else { return } + + // Debounce: ignore rapid taps + let now = Date() + guard now.timeIntervalSince(lastActionTime) >= actionDebounceInterval else { return } + lastActionTime = now + isProcessingAction = true defer { isProcessingAction = false } @@ -629,6 +647,12 @@ final class GameState { /// Player doubles down. func doubleDown() async { guard canDouble else { return } + + // Debounce: ignore rapid taps + let now = Date() + guard now.timeIntervalSince(lastActionTime) >= actionDebounceInterval else { return } + lastActionTime = now + isProcessingAction = true defer { isProcessingAction = false } @@ -655,6 +679,12 @@ final class GameState { /// Player splits the hand. func split() async { guard canSplit else { return } + + // Debounce: ignore rapid taps + let now = Date() + guard now.timeIntervalSince(lastActionTime) >= actionDebounceInterval else { return } + lastActionTime = now + isProcessingAction = true defer { isProcessingAction = false } @@ -701,6 +731,12 @@ final class GameState { /// Player surrenders. func surrender() async { guard canSurrender else { return } + + // Debounce: ignore rapid taps + let now = Date() + guard now.timeIntervalSince(lastActionTime) >= actionDebounceInterval else { return } + lastActionTime = now + isProcessingAction = true defer { isProcessingAction = false }