Let’s Go Bowling – An Entire Game – Solution

To make the conversion between simulating a single frame of bowling and an entire game isn’t that simple, which is mostly due to calculating the dreaded 10th Frame.

My solution draws heavily from the solution for May’s Exercise. It involves three parts:

First, you must create and fill the full 10 frames of bowling. For my solution, I used 12 frames, so an array of 12 frame structures is used. The extra two frames count for the 10th frame, which could potentially have up to three strikes. To accommodate those strikes, two extra frames are required in my approach.

Second, the scores need to be calculated. The score within each frame is useful, but to score an entire game, you need all 10 (or 12) frames to do the math.

Finally, special consideration must be taken for displaying the 10th frame. It not only looks different from all the other frames (see Figure 1), but it requires extra math to calculate the score and quite a bit of decision making to properly display the potential scoring possibilities.

Figure 1. Bowling simulation, 10 frames.

Figure 1. Bowling simulation, 10 frames.

For example, the 10th frame could be:

  • Two balls rolled, total less than 10.
  • A spare, which requires another ball to be rolled.
  • A strike, which requires two more balls to be rolled.
  • A strike, followed by up to two more strikes.

The code must evaluate each potential outcome.

Click this link to view the entire code. Below are highlights for each part of my solution. The bulk of the code uses the same frame structure, as well as the ball() and get_frame() functions as last month’s Solution.

First, the 12 frames are filled:

   /* Simulate 12 potential frames */
    for(x=0;x<12;x++)
        get_frame(&game[x]);

Yes, 12 frames. If the score in the 10th frame doesn’t require extra balls, then the 11th and 12th frames are ignored.

Second, the scores are calculated. While the original frame.score member is calculated as in last month’s solution, it’s updated here to reflect the cumulative score for each frame:

    /* properly calculate the scores */
    for(x=0;x<10;x++)
    {
        if( game[x].b2 == 'X' )
        {
            if( game[x+1].b2 == 'X' )
                score += 10 + game[x+1].ball1 + game[x+2].ball1;
            else
                score += 10 + game[x+1].score;
        }
        else if( game[x].b2 == '/' )
            score += 10 + game[x+1].ball1;
        else
            score += game[x].score;
        game[x].score = score;
    }

Exceptions are made based on whether the ball rolled is a strike or spare. I’ve used the frame.b2 member as a test because using the frame.score member doesn’t tell me whether the total was achieved by rolling one or two balls.

For strikes and spares, the next frame’s score is referenced as x+1. In the case of two strikes, frame x+2 is also accessed. The actual score is calculated in the score variable, which is used to update the frame.score member.

Output for the first 9 frames is pretty simple. It’s done one row at a time:

    /* Display first row, frame numbers */
    for(x=0;x<10;x++)
        printf(" %2d  ",x+1);
    putchar('\n');

    /* Second row, balls rolled */
    for(x=0;x<9;x++)
    {
        if( game[x].b2 == 'X')
            printf("|  |X");
        else
            printf("| %c|%c",game[x].b1,game[x].b2);
    }

The 10th frame requires some work and multiple decision trees. These cover the possibilities of rolling various combinations or strikes and spares plus the extra balls:

    /* Special output for 10th frame */
    if( game[x].b2 == 'X')
    {
        if( game[x+1].b2 == 'X')
        {
            if( game[x+2].b2 == 'X')
                printf("| X|X|X|\n");
            else
                printf("| X|X|%c|\n",game[x+2].b1);
        }
        else
            printf("| X|%c|%c|\n",game[x+1].b1,game[x+1].b2);
    }
    else if( game[x].b2 == '/')
    {
        if( game[x+1].b2 == 'X')
            printf("| %c|/|X|\n",game[x].b1);
        else
            printf("| %c|/|%c|\n",game[x].b1,game[x+1].b1);
    }
    else
        printf("| %c|%c| |\n",game[x].b1,game[x].b2);

For the strikes and spares, I used predefined the output in the printf() statements. So for a “turkey” (three strikes) in the 10th frame, three X characters are displayed. Otherwise, when a ball value must be specified, I use the %c placeholder.

Finally, the third row is output, which includes the scores.

    /* Third row, scores */
    for(x=0;x<9;x++)
    {
        printf("| %3d",game[x].score);
    }
    printf("|  %3d |\n",game[x].score);

    return(0);
}

As usual, your code can be different; no single, perfect solution exists for any programming puzzle. I’d like to have a more elegant decision tree for the 10th frame, but like many programmers, once I get something that works I generally don’t want to mess with it.

Leave a Reply