logo

UTK Notes


Introduction

This lab is simple on the surface, but definitely annoying to implement. It’ll be good for refining your logic & reasoning skills. That and you’ll learn how to score bowling!

Bowling

Here’s how bowling is scored at a high level:

  • A game consists of 10 frames
  • Each frame consists of 2 rolls
  • The 10th frame can have 3 rolls if the first 2 rolls are a strike or spare
  • A strike is when you knock down all 10 pins with the first roll of a frame
  • A spare is when you knock down all 10 pins with the second roll of a frame

Barring strikes & spares, a game’s total score is the sum of the number of pins knocked down in each frame. The highest possible score is 300, consisting of 12 strikes.

Strikes & spares are a bit more complicated. A strike’s value is 10 plus the number of pins knocked down in the next 2 rolls. A spare’s value is 10 plus the number of pins knocked down in the next roll. If it’s the 10th frame, then you will have 2 rolls to start. If you get a strike or spare, then you will have 1 more roll to finish the frame, making 3 rolls total. Otherwise it’s just 2 rolls for the last frame.

Program flow

Here’s a rough outline of the program flow:

  1. Player is promoted to enter their name
  2. Player enters the number of pins knocked down in each roll for every frame. If the first roll of a frame is a strike, then the 2nd roll is not prompted for. Although you will still need to store the 2nd roll’s value as 0, even though you won’t be asking for the user to enter the 2nd roll.
  3. Once all frames have been entered, evaluate (don’t print) the score for the player and store it
  4. Repeat until the player enters done when prompted for their name
  5. Print the scores for each player and the winner

Also note that the player can enter done at the beginning of the game, in which case no scores will be evaluated, and the print statement will be different.

Algorithm

Algorithmically speaking, we can break this down into 2 parts:

1. Scoring the game

  • For each frame, we need to know the number of pins knocked down in each roll and tally it up according to the scoring rules
  • If it’s the last frame, its score is simply the sum of the number of pins knocked down in each roll, since there are no frames after for strikes/spares

2. Scoring the frame

  • If it’s not a strike or spare, then the score is the sum of the number of pins knocked down in each roll
  • If it’s a strike, then the score is 10 plus the number of pins knocked down in the next 2 rolls
  • If it’s a spare, then the score is 10 plus the number of pins knocked down in the next roll

More specifically, scoring a frame is as follows:

For each frame

  • Get the number of pins knocked down in each roll
  • Determine if the frame was a strike or spare

If it was a strike, then get the current frame’s score plus the next 2 rolls If it was a spare, then get the current frame’s score plus the next roll Otherwise, just get the current frame’s score

  • Repeat until all frames are scored

Also if you get 2 strikes in a row, then the score (for that frame alone) is STRIKE + STRIKE + next_roll.

TLDR

The general formula for scoring a frame is:

1
2
3
4
5
6
7
8
score += current_frame_score
if current_frame.is_strike:
    if next_frame.is_strike:
        score += 10 + next_next_frame.first_roll
    else:
        score += next_frame.first_roll + next_frame.second_roll
elif current_frame.is_spare:
    score += next_frame.first_roll

The caveats to consider are

  1. You’ll need to score the 10th frame slightly differently. It should be evaluated separately from the other frames.
  2. If you get a strike in the 9th frame as well as the 10th frame, then you’ll need to make sure not to go a frame too far when scoring the 9th frame.

Input/Output requirements

There are no special formatting requirements for this lab. Just output the words & lines as shown in the sample output.

As for the input requirements, just make sure your data types are what they should be. No error checking is required.

Example Output 1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
Enter player's name (done for no more players): John
Enter score for frame 1, roll 1: 10
Enter score for frame 2, roll 1: 10
Enter score for frame 3, roll 1: 10
Enter score for frame 4, roll 1: 10
Enter score for frame 5, roll 1: 10
Enter score for frame 6, roll 1: 10
Enter score for frame 7, roll 1: 10
Enter score for frame 8, roll 1: 10
Enter score for frame 9, roll 1: 10
Enter score for frame 10, roll 1: 10
Enter score for frame 10, roll 2: 10
Enter score for frame 10, roll 3: 10
Enter player's name (done for no more players): Cheryl
Enter score for frame 1, roll 1: 8
Enter score for frame 1, roll 2: 1
Enter score for frame 2, roll 1: 0
Enter score for frame 2, roll 2: 9
Enter score for frame 3, roll 1: 2
Enter score for frame 3, roll 2: 8
Enter score for frame 4, roll 1: 10
Enter score for frame 5, roll 1: 6
Enter score for frame 5, roll 2: 3
Enter score for frame 6, roll 1: 7
Enter score for frame 6, roll 2: 0
Enter score for frame 7, roll 1: 5
Enter score for frame 7, roll 2: 2
Enter score for frame 8, roll 1: 10
Enter score for frame 9, roll 1: 0
Enter score for frame 9, roll 2: 6
Enter score for frame 10, roll 1: 2
Enter score for frame 10, roll 2: 8
Enter score for frame 10, roll 3: 10
Enter player's name (done for no more players): done

John scored 300.
Cheryl scored 122.
Cheryl did the worst by scoring 122.
John won the game by scoring 300.

Example Output 2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Enter player's name (done for no more players): John
Enter score for frame 1, roll 1: 8
Enter score for frame 1, roll 2: 1
Enter score for frame 2, roll 1: 0
Enter score for frame 2, roll 2: 9
Enter score for frame 3, roll 1: 2
Enter score for frame 3, roll 2: 8
Enter score for frame 4, roll 1: 10
Enter score for frame 5, roll 1: 6
Enter score for frame 5, roll 2: 3
Enter score for frame 6, roll 1: 7
Enter score for frame 6, roll 2: 0
Enter score for frame 7, roll 1: 5
Enter score for frame 7, roll 2: 2
Enter score for frame 8, roll 1: 10
Enter score for frame 9, roll 1: 0
Enter score for frame 9, roll 2: 6
Enter score for frame 10, roll 1: 2
Enter score for frame 10, roll 2: 8
Enter score for frame 10, roll 3: 10
Enter player's name (done for no more players): done

John scored 122.
John did the worst by scoring 122.
John won the game by scoring 122.

Requirements

As per the lab’s instructions, you’ll need to implement the following:

  • vector of strings to store the name(s) of the player(s)
  • vector of 21 ints to store 2 rolls per frame, plus 1 roll for the 10th frame (if applicable)
  • vector of ints to store the score(s) of the player(s)

  • each player must enter their name and subsequently their score for each roll of each frame
  • once the player has quit the game (by entering done when prompted for their name), then the game should be scored and the results should be printed

Testing

Probably won’t work on Windows

As usual, the “automated” testing for this lab is assuming you’re running on a Unix-like system. If you’re on Windows, the test commands below likely won’t work.

I will say though, if you are running Ubuntu or some Debian distro on Windows, then the following tests should work. Just make sure you have curl and make installed.

Installing curl & make on Ubuntu

1
sudo apt install curl make

Makefile

If you wish to test your program without inputting the values yourself, I’ve provided a Makefile that will both compile and test the program using the inputs from the outputs here and here based on the commands below.

The Makefile assumes your source file is named bowling.cpp. If it’s not then change it to that if you wish to test with the Makefile. Also make sure to run the following commands in the same directory as your bowling.cpp.

Download Makefile

1
curl https://raw.githubusercontent.com/Ethan0429/cs102-writeups/main/lab7/Makefile --output Makefile

or

1
curl https://utknotes.pisaucer.com/CS102/EthanNotes/Lab07/Makefile.txt --output Makefile

Compile

compiles your program

1
make

Running the tests

Make sure you’ve at least completed the gameplay loop of the program before running the tests. Basically, don’t test until you have everything and just want to make sure the scoring works. Also, the following tests omit the input from the output. So the Canvas output will show the inputs printed along with the outputs, whereas the test outputs will not show those inputs (the pins knocked in each roll). This is just a result of the test(s), and does not reflect your program’s full output in that sense.

tests the 1st input from output 1

1
make test1

tests the 2nd input from output 2

1
make test2

You’ll want to test for a bunch of input types as well, since the two provided on Canvas won’t cover every case. The following command will test 5 player inputs, each of which will have random rolls each frame. You can view the inputs from the test.txt file that is generated once the command is run. I can’t provide a solution output, so you’ll have to check your scores yourself. You can do it manually, or I recommend using this bowling score calculator

tests for random inputs (assumes you have python3 installed)

1
make random

You don’t need to run make to compile before testing. make test1, make test2, and make random will compile the program for you as well as run the tests.

Lastly, I’ll mention that if either of the make tests don’t print anything out, it’s likely because you’re handling the incorrect amount of rolls/frames or your output doesn’t match the format from the example shown earlier.

Bye

Good luck! Open a ticket on the Discord or come to office hours if you have any questions, as always.