Check your understanding of the previous reading: the Ghost Hunt program.

Question 1

In the Ghost Hunt program, there are six functions that are used to handle the grid (a list of lists of Tiles). These functions were either mutable or immutable, depending on whether they changed the grid or not. Note that just because a function returns a new grid does not mean it is mutable; a function is only mutable if it modifies the grid that was passed into it.

Which of the following grid functions were mutable in that they modified the actual grid that was passed into the function?

Select every one that applies, then check.

  • Not mutable. make_ghost_grid doesn't even take a grid as a parameter: it builds one from scratch with make_empty_grid and returns it.
  • Not mutable. It doesn't take a grid as a parameter either; it builds and returns a brand new one.
  • Correct. add_treat_if_empty sets grid[y][x].text = TREAT directly on the grid it was given.
  • Not mutable. It only reads len(grid) to know the size; it never assigns into the grid, only returns a list of positions.
  • Correct. fill_in_board assigns grid[y][x].text = GHOST and calls add_treat_if_empty on the grid it was given.
  • Not mutable. draw_grid only reads the grid's tiles to build a separate display list; it never assigns into the grid.

Question 2

The choose_ghost_spots function returns a list of list of integers. Which of the following is the best explanation of that data?

Select one answer, then check.

  • Correct. Each call to positions.append([xs.pop(), ys.pop()]) adds one [x, y] pair for one ghost, so there is one two-element inner list per ghost.
  • Not quite. That would describe a full grid of 0s and 1s, but choose_ghost_spots only builds a short list of [x, y] positions, one per ghost.
  • Not quite, for the same reason: there's no full grid of 0s and 1s here, only one short [x, y] list per ghost.
  • Not quite. That would be two long lists (all the xs, then all the ys), but the code pairs one x with one y per ghost instead: [xs.pop(), ys.pop()].

Question 3

Look up the shuffle function in the Python standard library. Which of the following best describes what it does?

Select one answer, then check.

  • Not quite. shuffle returns None; it doesn't build and return a new list.
  • Correct. random.shuffle reorders the list it is given in place and returns None, which is exactly why the code calls it as a statement, shuffle(xs), rather than assigning its result.
  • Not quite. That describes sorted, not shuffle. Shuffling randomizes order; it doesn't sort.
  • Not quite. That describes sorted(..., reverse=True), not shuffle.
  • Not quite. That describes random.choice, which the program also imports but doesn't use for this part.
  • Not quite. Popping a random element isn't what shuffle does; the code gets that removal effect separately, with .pop().

Question 4

The grid in this project is represented as a list of list of Tile objects. In some places, we access the grid using expressions like grid[y][x] (e.g., in fill_in_board and flip_tile). Why do we use grid[y][x] instead of grid[x][y]?

Select one answer, then check.

  • Correct. make_empty_grid builds the grid by looping for y in range(size) on the outside and for x in range(size) on the inside, appending each row before appending it to the grid, so the first index picks a row (y) and the second picks a column within it (x).
  • Not quite. It's the other way around: make_empty_grid loops over y for the outer list and x for the inner one.
  • Not quite. There's no separate list of all x-coordinates and all y-coordinates here; each row is a list of Tile objects, not raw coordinates.
  • Not quite, for the same reason as the previous option; there's no such split into two flat coordinate lists.
  • Not quite. The grid isn't square-symmetric in how it's built; the order the loops run in fixes which index is the row and which is the column.
  • Not quite. Zero-based indexing applies to both orders equally; it doesn't explain why y comes first specifically.

Question 5

In the State of this application, we have a field named score that keeps track of the player's score. Which of these best describes how the score field is updated during the game?

Select one answer, then check.

  • Not quite. flip_tile only increments score inside the if tile.text == GHOST: check, not on every flip.
  • Not quite. score only ever goes up, via state.score += 1.
  • Correct. flip_tile runs if tile.text == GHOST: state.score += 1, so only flipping a ghost tile raises the score.
  • Not quite. Flipping an empty or treat tile leaves score unchanged; it never decreases.
  • Not quite. There's no timer anywhere in State or in the routes; the game has no time component.