# Introduction to Computer Programming: Lab 6

## Grid, Grok, Go!

### Goals

• practice manipulating lists of lists
• gain experience using turtle graphics
• understand difference between internal state and graphical state
• experiment with simple grid-based game

### Instructions

• Work on this lab with your partner (or on your own if you have not been assigned one).

• Work with the supplied starter file.

• You are welcome to download a runnable solution module called `lab6x`.

• In the common case, you will not complete the exercises during our scheduled lab. It is then up to you to complete the lab on your own time.

### Exercises

1. Warmup. Consider these examples. Experiment with lists of lists by typing examples into IDLE's shell after running the `lab6_examples.py` module. You should aim to try every function the example file at least once before continuing. Use some of the functions in combination to assist your understanding as in:

``````>>> g = make_empty_grid(5, 3, False)
>>> g
>>> g[1]
>>> g[1][2] = True
>>> g[1]
>>> grid_to_string(g)
>>> print(grid_to_string(g))
>>> swap_rows(g, 0, 1)
>>> print(grid_to_string(g))
...``````
2. Complete `paint(color, p)` so that it draws a square colored `color` at the row-column coordinates indicated by the pair `p`. Use `to_pixels` and the `goto`, `color` and `stamp` functions from the `turtle` module. You can test the function like this:

``````>>> open_window(8, 5, 'blue', 'test')
>>> paint('red', (6, 2))``````

This should open an 8-row and 5-column window with a blue background and a title of "test" and then paint a red square at row 6 and column 2 of that small window:

The string representing the paint color can be any valid

Challenge version: add code to `paint` so that if the row or column coordinate is "out of bounds" a message is printed (using the regular `print` function) indicating that fact (and nothing gets painted in the turtle-graphics window).

3. Complete `randomize_grid(grid)` so that it makes every entry of the grid `True` or `False`, with equal likelihood, at random. Simple examination in the shell should suffice for testing, as in:

``````>>> g = make_empty_grid(4, 2, False)
>>> g
[[False, False], [False, False], [False, False], [False, False]]
>>> randomize_grid(g)
>>> g
[[True, True], [True, False], [False, False], [True, False]]``````
4. Complete `paint_grid(grid)` so that for `True` values in `grid` correspond to squares painted with color `ON_COLOR` and `False` values correspond to squares painted with `OFF_COLOR`. Now running the grid-grok-go REPL (`grid_repl()`) should properly start the game, displaying a 5x5 board with randomly placed squares. You can use the REPL to test the remainder of the functions on this lab.

5. Complete `toggle_grid(grid)` so that it inverts every entry of Boolean-valued grid (`False` becomes `True` and vice versa). Example:

``````>>> g = make_empty_grid(4, 2, False)
>>> g
[[False, False], [False, False], [False, False], [False, False]]
>>> randomize_grid(g)
>>> g
[[True, True], [True, False], [False, False], [True, False]]
>>> toggle_grid(g)
[[False, False], [False, True], [True, True], [False, True]]``````
6. Complete `rotate_grid(grid)` so that it returns a new grid that has been rotated 90 degrees; for example:

``````>>> g
[[True, True], [True, False], [False, False], [True, False]]
>>> rotate_grid(g)
[[True, True, False, True], [True, False, False, False]]``````

Challenge version: write `rotate_grid_in_place(grid)` that can assume `grid` is square (i.e., that it has the same number of rows and columns) and then rotates the contents of `grid` in place meaning that no new grid is created; nothing is returned.

7. Complete `swap_columns(grid, i, j)` so that it exchanges columns `i` and `j` in `grid`. For example:

`````` >>> print(grid_to_string(g))
--*-*
****-
*----
>>> swap_columns(g, 0, 4)
>>> print(grid_to_string(g))
*-*--
-****
----*``````
8. Complete `slide_row_left(grid, r)` so that it moves the contents of row `r` in `grid` "left" one position so that what was in the first column is overwritten by what was in the next column, etc. The rightmost element of the row is set to `False`. Example:

``````>>> print(grid_to_string(g))
*_*__
_**_*
_***_
>>> slide_row_left(g, 1)
*_*__
**_*_
_***_``````
9. Complete `slide_column_down(grid, c)` so that it moves the contents of column `c` in `grid` "down" one position so that what was in the last row is overwritten by what was immediately above it, etc. The topmost element of the row is set to `False`. Example:

``````>>> print(grid_to_string(g))
*_*__
_**_*
_***_
>>> slide_column_down(g, 2)
*_-__
_**_*
_***_``````
10. Complete `count_sw(grid)` so that, assuming grid is square, it returns the number of `True`s along the diagonal running "southwest" from the upper-right corner of the grid to the lower-left corner. For example:

`````` >>> print(grid_to_string(g))
-*-*
***-
*---
*-**
>>> count_sw(g)   # the SW diagonal consists of **-*
3``````
11. Complete `get_column_counts(grid)` so that it returns a list of the number of `True`s in each column. For example:

`````` >>> print(grid_to_string(g))
--*-*
****-
*----
>>> get_column_counts(g)
[2, 1, 2, 1, 1]``````

12. If you have completed the rest of the lab to this point, the game should be roughly playable. Add code to the REPL loop in `grid_repl` so it uses `get_row_counts`, `get_column_counts`, `count_se` and `count_sw` to check if the player wins (gets a row, column or diagonal full) or loses (leaves a row, column or diagonal entirely blank). Winning or losing should cause the REPL loop to stop (as it does already for quitting).