1- from random import randint
2- from typing import cast , Generator , List , Optional
1+ from random import randrange
2+ from typing import Any , cast , Dict , Generator , List , Optional , Tuple
33
4- from base .cell import Cell
4+ from base .cell import Cell , is_cell
5+
6+
7+ Key = Tuple [int , int ]
8+ CellList = List [Cell ]
59
610
711class Grid :
@@ -18,23 +22,28 @@ def columns(self) -> int:
1822 def size (self ) -> int :
1923 return self .rows * self .columns
2024
25+ @property
26+ def dimensions (self ) -> Key :
27+ return self .rows , self .columns
28+
29+ @property
30+ def data (self ) -> Dict :
31+ return self ._data
32+
2133 @property
2234 def deadends (self ) -> List [Cell ]:
23- deadends_list = []
24- for cell in self .each_cell ():
25- if len (cell .links ) == 1 :
26- deadends_list .append (cell )
27- return deadends_list
35+ return [cell for cell in self .each_cell () if len (cell .links ) == 1 ]
2836
2937 def __init__ (self , rows : int , columns : int ) -> None :
3038 if rows is None or rows < 2 :
3139 raise ValueError ("Rows must be an integer greater than 1" )
3240 if columns is None or columns < 2 :
3341 raise ValueError ("Columns must an integer greater than 1" )
3442
35- self ._rows = rows # type: int
36- self ._columns = columns # type: int
37- self ._grid = self .prepare_grid ()
43+ self ._rows : int = rows
44+ self ._columns : int = columns
45+ self ._data : Dict = {}
46+ self ._grid : List [List [Cell ]] = self .prepare_grid ()
3847 self .configure_cells ()
3948
4049 def cell_at (self , row : int , column : int ) -> Optional [Cell ]:
@@ -44,32 +53,79 @@ def cell_at(self, row: int, column: int) -> Optional[Cell]:
4453 return None
4554 return self ._grid [row ][column ]
4655
47- def set_cell_at (self , row : int , column : int , cell : Cell ) -> None :
48- self ._grid [row ][column ] = cell
56+ def set_cell_at (self , row : int , column : int , value : Cell ) -> None :
57+ self ._grid [row ][column ] = value
4958
5059 def prepare_grid (self ) -> List [List [Cell ]]:
5160 return [[Cell (row , column ) for column in range (self .columns )] for row in range (self .rows )]
5261
5362 def configure_cells (self ) -> None :
63+ """
64+ Create all the north/sout/east/west dependencies of the cells
65+ """
5466 for cell in self .each_cell ():
55- cell .north = self .cell_at (cell .row - 1 , cell .column )
56- cell .south = self .cell_at (cell .row + 1 , cell .column )
57- cell .east = self .cell_at (cell .row , cell .column + 1 )
58- cell .west = self .cell_at (cell .row , cell .column - 1 )
67+ row = cell .row
68+ column = cell .column
69+
70+ cell .north = self [row - 1 , column ]
71+ cell .south = self [row + 1 , column ]
72+ cell .east = self [row , column + 1 ]
73+ cell .west = self [row , column - 1 ]
5974
6075 def random_cell (self ) -> Cell :
61- column = randint (0 , self .columns - 1 )
62- row = randint (0 , self .rows - 1 )
63- return cast (Cell , self . cell_at ( row , column ) )
76+ row = randrange (0 , self .rows )
77+ column = randrange (0 , self .columns )
78+ return cast (Cell , self [ row , column ] )
6479
65- def each_row (self ) -> Generator :
80+ def each_row (self ) -> Generator [ CellList , None , None ] :
6681 for row in range (self .rows ):
6782 yield self ._grid [row ]
6883
84+ # TODO: Add tests
85+ def each_column (self ) -> Generator [CellList , None , None ]:
86+ for column in zip (* self ._grid ):
87+ yield column
88+
6989 def each_cell (self ) -> Generator :
70- for row in range ( self .rows ):
71- for column in range ( self . columns ) :
72- yield self . cell_at ( row , column )
90+ for row in self .each_row ( ):
91+ for cell in row :
92+ yield cell
7393
7494 def contents_of (self , cell : Cell ) -> str :
7595 return " "
96+
97+ def __getitem__ (self , key : Key ) -> Optional [Cell ]:
98+ if not is_key (key ):
99+ raise IndexError ('Only grid[row,col] __getitem__ calls are supported' )
100+ return self .cell_at (* key )
101+
102+ if is_key (key ):
103+ row , column = key
104+ if row < 0 or row > self .rows - 1 :
105+ return None
106+ if column < 0 or column > self .columns - 1 :
107+ return None
108+ return self ._grid [row ][column ]
109+
110+ def __setitem__ (self , key : Key , value : Cell ) -> None :
111+ if not (is_key (key ) and is_cell (value )):
112+ raise IndexError ('Only grid[row,col] __setitem__ calls are supported' )
113+ self .set_cell_at (* key , value )
114+
115+ def __contains__ (self , other : Cell ) -> bool :
116+ if is_cell (other ):
117+ for cell in self .each_cell ():
118+ if cell == other :
119+ return True
120+ return False
121+
122+
123+ def is_key (key : Key ) -> bool :
124+ """
125+ Runtime check for key correctness
126+ """
127+ return type (key ) == tuple and len (key ) == 2 and not any (type (value ) != int for value in key )
128+
129+
130+ def is_grid (grid : Any ) -> bool :
131+ return isinstance (grid , Grid )
0 commit comments