CompSci.rocks
FRQcsapa

TokenPass: 2013 FRQ 2

A step-by-step solution to the 2013 AP CSA FRQ 2 (TokenPass), covering filling an array with bounded random values and distributing tokens around an array with wraparound in Java.

A circular token-passing game gives this AP Computer Science A free-response question its shape — the interesting part isn't handing out tokens one at a time, it's making that hand-out wrap back around to the start of the board once it reaches the far end.

What This FRQ Tests

  • AP CSA units: Unit 6 (Array) and Unit 4 (Iteration)
  • Core skill: filling an array with bounded random integers, and looping around an array's ends using the modulus operator
  • Secondary skill: tracking a loop counter that's independent of the array position being modified, since one turn's "collected tokens" count has nothing to do with the array's length
  • Official category: content-wise, this is "Array" work — Unit 6 territory that today's fixed FRQ order always slots at FRQ 3. 2013 predates that standardization, and the exam's own booklet prints this question second, right after an ArrayList-based first question.

The Setup

  • TokenPass holds:
    • private int[] board — one element per player, holding that player's current token count
    • private int currentPlayer — whose turn it currently is
  • You're asked to write:
    • the constructor TokenPass(int playerCount) — fills board with playerCount random values from 1 to 10, and sets currentPlayer to a random valid index
    • distributeCurrentPlayerTokens() — collects the tokens at currentPlayer's position and hands them out one at a time to each following position, wrapping back to position 0 after the highest position

Part (a): Writing the TokenPass(int playerCount) constructor

Step-by-Step Approach

  1. Create board as a new array of size playerCount.
  2. Loop over every index of board, assigning each a random integer from 1 to 10, inclusive.
  3. Separately, set currentPlayer to a random integer from 0 to playerCount - 1, inclusive.

The Code

public TokenPass(int playerCount)
{
    board = new int[playerCount];

    for (int i = 0; i < board.length; i++)
    {
        board[i] = (int) (Math.random() * 10) + 1;
    }

    currentPlayer = (int) (Math.random() * playerCount);
}

Why Each Piece Matters

  • Math.random() returns a double in the range [0.0, 1.0). Multiplying by 10 gives [0.0, 10.0), and casting to int truncates that down to a whole number from 0 to 9. Adding 1 shifts the whole range to 1 through 10, matching "1 to 10, inclusive" exactly.
  • currentPlayer skips that + 1 — multiplying Math.random() by playerCount and truncating gives a value from 0 to playerCount - 1, which is precisely board's valid index range.
  • The (int) cast has to wrap the entire Math.random() * 10 expression, not just Math.random() by itself — casting Math.random() to int first would always produce 0, since Math.random() alone is always less than 1.

Tracing the Example

The question doesn't give a deterministic worked example of the constructor's output — since it deliberately fills the board with random values, there's no single fixed input/output pair to trace here. The PDF's example board ([3, 2, 6, 10] with currentPlayer = 2, for a 4-player game) is presented only as one possible result of running this constructor, not a value the constructor is expected to reproduce exactly.

Common Mistakes to Avoid

  • Casting Math.random() to int before multiplying — ((int) Math.random()) * 10 + 1 always evaluates to 1, since (int) Math.random() is always 0.
  • Forgetting the + 1 on the token counts, which produces a range of 0-9 instead of the required 1-10.
  • Adding + 1 to the currentPlayer calculation, which would allow an out-of-bounds index of playerCount.
  • Referencing board.length before board has actually been assigned a new array.

Part (b): Writing distributeCurrentPlayerTokens()

The Rule, Broken Down

  1. Read and remember how many tokens are at currentPlayer's position, then set that position to 0 — the tokens are "collected and removed."
  2. Hand out one token at a time, starting with the very next position after currentPlayer.
  3. Once the highest position receives a token, wrap back around to position 0.
  4. Stop once every collected token has been handed out.
  5. currentPlayer itself must not change.

Step-by-Step Approach

  1. Save board[currentPlayer] as the number of tokens to distribute, then zero out that position.
  2. Use a separate loop variable — not currentPlayer — to track which position is currently receiving a token, starting from currentPlayer.
  3. Repeat once per collected token: advance that position by one, wrapping with % board.length, and add one token there.

The Code

public void distributeCurrentPlayerTokens()
{
    int numTokens = board[currentPlayer];
    board[currentPlayer] = 0;

    int position = currentPlayer;

    for (int i = 0; i < numTokens; i++)
    {
        position = (position + 1) % board.length;
        board[position] = board[position] + 1;
    }
}

Why Each Piece Matters

  • board[currentPlayer] is read and saved before it's zeroed out — zeroing first would lose the very count needed to know how many times to loop.
  • position starts as a copy of currentPlayer's value, not currentPlayer itself, so the loop is free to move it around without ever touching the actual currentPlayer field.
  • (position + 1) % board.length is what makes the wraparound automatic: once position reaches board.length - 1, adding 1 gives board.length, and % board.length brings it right back to 0 — with no separate if needed to catch the wraparound case.
  • The increment always happens on position, recomputed fresh at the top of each loop iteration — never on currentPlayer.

Tracing the Example

Using the question's own 4-player example — board = [3, 2, 6, 10], currentPlayer = 2:

Step position board after this step
start numTokens = 6, board[2] set to 0 → [3, 2, 0, 10]
1st token (2+1)%4 = 3 [3, 2, 0, 11]
2nd token (3+1)%4 = 0 [4, 2, 0, 11]
3rd token (0+1)%4 = 1 [4, 3, 0, 11]
4th token (1+1)%4 = 2 [4, 3, 1, 11]
5th token (2+1)%4 = 3 [4, 3, 1, 12]
6th token (3+1)%4 = 0 [5, 3, 1, 12]

Final board: [5, 3, 1, 12] — matching the question's own result exactly, and matching the visited positions (3, 0, 1, 2, 3, 0) the question's own prose narrative describes step by step.

Common Mistakes to Avoid

  • Incrementing currentPlayer directly instead of a separate position variable — this violates the "the current player has not changed" postcondition.
  • Reading board[currentPlayer] for numTokens after it's already been zeroed out, instead of saving the count in a local variable first.
  • Using an if-statement that only handles wrapping past the last index once, instead of the modulus operator — this can break if numTokens is large enough to wrap all the way around the board more than once.
  • Writing the wraparound as position % board.length + 1 instead of (position + 1) % board.length — these are not equivalent, and the former can produce an out-of-range index.

Key Takeaways

  • Wrapping an index back to 0 after it passes the end of an array is a job for the modulus operator — (index + 1) % array.length — not a series of manual if-checks.
  • When "how many times to loop" comes from a value you're about to overwrite, save that value in a local variable before changing anything.
  • A method that isn't allowed to change one particular field (currentPlayer, here) should route all of its work through a separate local variable instead of touching that field directly.

Related FRQs