-class Cell(object):
- """Represents a single cell/value within a sudoku grid."""
-
- ### Accessors
-
- def _get_solved(self):
- """True iff this cell has been solved."""
- return len(self._values) == 1
- solved = property(_get_solved)
-
- def _get_value(self):
- """Returns this cell's value, if it has one known."""
- if self.solved:
- return self._values[0]
- return None
- value = property(_get_value)
-
- def _get_row(self):
- """Returns the Row object associated with this cell."""
- return self._grid._rows[self._row]
- row = property(_get_row)
-
- def _get_column(self):
- """Returns the Column object associated with this cell."""
- return self._grid._columns[self._col]
- column = property(_get_column)
-
- def _get_box(self):
- """Returns the Box object associated with this cell."""
- # Some actual math required here!
- # Row 0..2 -> box 0..2
- # Col 0..2 -> box 0, 3, 6 (box col 0)
- box_row = self._row // self._grid._box_height
- box_col = self._col // self._grid._box_width
- box_idx = box_row * self._grid._box_height + box_col
- return self._grid._boxes[box_idx]
- box = property(_get_box)
-
- def __init__(self, grid, row, column):
- self._grid = proxy(grid)
- self._row = row
- self._col = column
- self._values = range(self._grid.size)
- self._normalized = False
-
- def set(self, value, normalize=True):
- """Sets the value of this cell. If `normalize` is True or omitted, the
- grid will be updated accordingly.
- """
- self._values = [value]
- if normalize:
- self._normalized = False
- self.normalize()
-
-
-
- def normalize(self):
- """Checks to see if this cell has only one possible value left. If
- so, sets that as its value and eliminates it from every related cell.
- This method is exhaustive; that repeated calls should have no effect.
- """
-
- if self._normalized:
- # Already done
- return
-
- # Set this now just in case of infinite looping
- self._normalized = True
-
- if not self.solved:
- # Don't know the value yet
- return
-
- # Elimination time
- for group_type in 'row', 'column', 'box':
- group = getattr(self, group_type)
- for cell in group.cells:
- if cell == self:
- continue
- cell.eliminate(self.value)
-
-
- def eliminate(self, value):
- """Eliminates the given value as a possibility for this cell."""
- if value in self._values:
- self._values.remove(value)
-
- if len(self._values) == 0:
- # XXX give me a real exception here
- raise Exception
-
- self._normalized = False
- self.normalize()
-