Comet pins the field sketch to the wall. "Pip needs a real map," she says. "One the Rover can ask questions, like where are the rocks?"
Wren reads his notes from week 3. "What does the evidence say about Rover?" he asks. "We hid its state behind methods, and it helped. Let's do the same for the field."
Nova projects two file icons, field_data.py and grid.py, with a line between them. "How can I help?" she asks. "Keep the data in one file and the class in another."
"Lead programmer," Comet says, "two files today. Then we put Pip on the map."
field_data.py holds made-up data from the FieldSim story. It has the field map, the four field samples and a catalog for later weeks.
grid.py holds class FieldGrid. It keeps the field as a list of lists in _cells, hidden behind methods, like Rover keeps its state.
| Method | What it gives back or does |
|---|---|
| height(), width() | The number of rows, and the number of columns. |
| in_bounds(row, col) | True if the cell is inside the field. |
| cell(row, col) | The mark in that cell. |
| set_cell(row, col, mark) | Puts a new mark in that cell. |
| is_open(row, col) | True if the cell is in bounds and not a rock. |
| count(mark) | How many cells hold that mark. |
| show(rover=None) | Prints the field, with R where a rover is. |
# field_data.py
# Made-up data for the Larkspur test field (FieldSim story).
# "." open ground, "#" rock, "*" a sample spot.
FIELD = [
"..*..#",
".#....",
"...#*.",
"*.....",
"..#..*",
]
# label, kind, grams, row, col (the four spots marked * above)
FIELD_SAMPLES = [
("S01", "basalt", 42, 0, 2),
("S02", "quartz", 18, 2, 4),
("S03", "clay", 65, 3, 0),
("S04", "mica", 7, 4, 5),
]
# The whole catalog of samples the crew has logged (weeks 8 to 12).
CATALOG = [
("S01", "basalt", 42),
("S02", "quartz", 18),
("S03", "clay", 65),
("S04", "mica", 7),
("S05", "granite", 30),
("S06", "shale", 51),
("S07", "slate", 12),
("S08", "flint", 88),
("S09", "chalk", 25),
("S10", "sandstone", 39),
] # grid.py
# A FieldGrid is the test field as a 2D list of one-letter cells.
class FieldGrid:
"""The test field: rows of cells, each ".", "#" or "*"."""
def __init__(self, rows):
self._cells = []
for row in rows:
self._cells.append(list(row))
def height(self):
return len(self._cells)
def width(self):
return len(self._cells[0])
def in_bounds(self, row, col):
return 0 <= row < self.height() and 0 <= col < self.width()
def cell(self, row, col):
return self._cells[row][col]
def set_cell(self, row, col, mark):
self._cells[row][col] = mark
def is_open(self, row, col):
return self.in_bounds(row, col) and self.cell(row, col) != "#"
def count(self, mark):
total = 0
for row in self._cells:
for c in row:
if c == mark:
total += 1
return total
def show(self, rover=None):
for r in range(self.height()):
line = ""
for c in range(self.width()):
if rover is not None and rover.get_row() == r and rover.get_col() == c:
line += "R"
else:
line += self._cells[r][c]
print(line) # grid_demo.py
from field_data import FIELD
from grid import FieldGrid
grid = FieldGrid(FIELD)
grid.show()
print(grid.height(), "rows,", grid.width(), "columns")
print("Rocks:", grid.count("#"))
print("Sample spots:", grid.count("*"))
print("Open ground:", grid.count(".")) ..*..# .#.... ...#*. *..... ..#..* 5 rows, 6 columns Rocks: 4 Sample spots: 4 Open ground: 22
# grid_rover.py
from field_data import FIELD
from grid import FieldGrid
from rover import Rover
grid = FieldGrid(FIELD)
pip = Rover("Pip", 2, 1)
grid.show(pip)
print(grid.cell(2, 1)) ..*..# .#.... .R.#*. *..... ..#..* .
Pip has collected the sample at (0, 2), so mark that cell open. Make grid_change.py:
# grid_change.py
from field_data import FIELD
from grid import FieldGrid
grid = FieldGrid(FIELD)
grid.set_cell(0, 2, ".")
print("Sample spots:", grid.count("*"))
print(FIELD[0]) In grid_demo.py, take the quotes away from the rock mark: grid.count(#). Save and run it.
File "grid_demo.py", line 8
print("Rocks:", grid.count(#))
^
SyntaxError: '(' was never closed A real map for Pip. Tomorrow you will find out what happens at the edges.