1package examples
2
3// Game contains the state of a bowling game.
4type Game struct {
5	rolls   []int
6	current int
7}
8
9// NewGame allocates and starts a new game of bowling.
10func NewGame() *Game {
11	game := new(Game)
12	game.rolls = make([]int, maxThrowsPerGame)
13	return game
14}
15
16// Roll rolls the ball and knocks down the number of pins specified by pins.
17func (self *Game) Roll(pins int) {
18	self.rolls[self.current] = pins
19	self.current++
20}
21
22// Score calculates and returns the player's current score.
23func (self *Game) Score() (sum int) {
24	for throw, frame := 0, 0; frame < framesPerGame; frame++ {
25		if self.isStrike(throw) {
26			sum += self.strikeBonusFor(throw)
27			throw += 1
28		} else if self.isSpare(throw) {
29			sum += self.spareBonusFor(throw)
30			throw += 2
31		} else {
32			sum += self.framePointsAt(throw)
33			throw += 2
34		}
35	}
36	return sum
37}
38
39// isStrike determines if a given throw is a strike or not. A strike is knocking
40// down all pins in one throw.
41func (self *Game) isStrike(throw int) bool {
42	return self.rolls[throw] == allPins
43}
44
45// strikeBonusFor calculates and returns the strike bonus for a throw.
46func (self *Game) strikeBonusFor(throw int) int {
47	return allPins + self.framePointsAt(throw+1)
48}
49
50// isSpare determines if a given frame is a spare or not. A spare is knocking
51// down all pins in one frame with two throws.
52func (self *Game) isSpare(throw int) bool {
53	return self.framePointsAt(throw) == allPins
54}
55
56// spareBonusFor calculates and returns the spare bonus for a throw.
57func (self *Game) spareBonusFor(throw int) int {
58	return allPins + self.rolls[throw+2]
59}
60
61// framePointsAt computes and returns the score in a frame specified by throw.
62func (self *Game) framePointsAt(throw int) int {
63	return self.rolls[throw] + self.rolls[throw+1]
64}
65
66const (
67	// allPins is the number of pins allocated per fresh throw.
68	allPins          = 10
69
70	// framesPerGame is the number of frames per bowling game.
71	framesPerGame    = 10
72
73	// maxThrowsPerGame is the maximum number of throws possible in a single game.
74	maxThrowsPerGame = 21
75)
76