Skip to content

Instantly share code, notes, and snippets.

@ksoftllc
Created September 26, 2022 23:56
Show Gist options
  • Save ksoftllc/075386d7647218fb55692dd9cc1c1d80 to your computer and use it in GitHub Desktop.
Save ksoftllc/075386d7647218fb55692dd9cc1c1d80 to your computer and use it in GitHub Desktop.
struct Frame {
enum Change {
case addRoll(_ roll: Int)
case setCurrentFrame(_ newValue: Bool)
}
static let Strike = 10
static let FullRackOfPins = 10
static let Gutter = 0
static let LastFrame = 10
static let EmptyBoxScore = " "
let frameNumber: Int
var rolls = [Int]()
var isCurrentFrame = false
// computed properties
var isStrike: Bool { (rolls.first == 10) }
var isSpare: Bool { rolls.count >= 2 && (rolls[0] + rolls[1] == 10) }
var showExtraRolls: Bool { frameNumber == Self.LastFrame }
var isAcceptingRolls: Bool { isCurrentFrame || ((isSpare || isStrike) && (rolls.count < 3)) }
var isComplete: Bool { ((isSpare || isStrike) && (rolls.count == 3)) || ((!isSpare && !isStrike) && rolls.count == 2) }
var value: Int { rolls.reduce(0, +) }
var firstRollRepresentation: String {
isStrike ? " " : rolls.first == 0 ? "-" : rolls.count == 0 ? " " : "\(rolls.first!)"
}
var secondRollRepresentation: String {
isStrike ? "X" : isSpare ? "/" : rolls.count < 2 ? " " : "\(rolls[1])"
}
var boxScore: String { "\(firstRollRepresentation)\(secondRollRepresentation)" }
func alter(_ c: Change...) -> Self { c.reduce(self) { $0.alter($1) } }
private func alter(_ change: Change) -> Self {
var updatedFrame = self
switch change {
case .addRoll(let roll):
if isAcceptingRolls {
updatedFrame.rolls.append(roll)
}
case .setCurrentFrame(let newValue):
updatedFrame.isCurrentFrame = newValue
}
return updatedFrame
}
}
extension Frame: CustomStringConvertible {
var description: String {
let status = isSpare ? "spare" : isStrike ? "strike" : isComplete ? "open" : "incomplete"
return
"Frame \(frameNumber) boxScore: \(boxScore) rolls: \(rolls) status: \(status) value: \(value) completed: \(isComplete)"
}
}
var frame1 = Frame(frameNumber: 1, isCurrentFrame: true)
var frame2 = Frame(frameNumber: 2, isCurrentFrame: false)
var frame3 = Frame(frameNumber: 3, isCurrentFrame: false)
print(frame1, "\n", frame2, "\n", frame3)
print("--- before any rolls ---")
// bowl first frame
frame1 = frame1.alter(.addRoll(10))
print(frame1, "\n", frame2, "\n", frame3)
print("--- end of frame 1 ---")
// bowl second frame
frame1 = frame1.alter(.setCurrentFrame(false))
frame2 = frame2.alter(.setCurrentFrame(true))
frame2 = frame2.alter(.addRoll(7))
frame1 = frame1.alter(.addRoll(7))
frame2 = frame2.alter(.addRoll(3))
frame1 = frame1.alter(.addRoll(3))
print(frame1, "\n", frame2, "\n", frame3)
print("--- end of frame 2 ---")
// bowl third frame
frame2 = frame2.alter(.setCurrentFrame(false))
frame3 = frame3.alter(.setCurrentFrame(true))
frame3 = frame3.alter(.addRoll(9))
frame2 = frame2.alter(.addRoll(9))
frame3 = frame3.alter(.addRoll(0))
print(frame1, "\n", frame2, "\n", frame3)
print("--- end of frame 3 ---")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment