Last active
June 11, 2020 22:46
Revisions
-
ksylvan revised this gist
Jun 11, 2020 . 1 changed file with 40 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -103,3 +103,43 @@ def __setitem__(self, k, v): print(f"{r}X{c} Grid with {m} mines:\n") print(o) print("") # Sample output: # # 16X12 Grid with 4 mines: # # 11.......... # X1.......... # 11.......... # ............ # ............ # ............ # ............ # ............ # ...111...... # ...1X1...... # ...222...... # ...1X1...... # ...111...... # ............ # .111........ # .1X1........ # # 8X8 Grid with 5 mines: # # 11..111. # X1..1X21 # 11.1222X # ...1X111 # ...111.. # ........ # ......11 # ......1X # # 5X5 Grid with 20 mines: # # XX4XX # XX7XX # XXXXX # XXXXX # X434X -
ksylvan created this gist
Jun 11, 2020 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,105 @@ from random import randrange class MinesGrid: # Implement a sparse array to optimize space. MINE = -1 class Row: # Each row in the __a dict has the following # structure a list, containing: # [ empty_cells, {} ] def __init__(self, cols): self.__cols = cols self.__empty_cells = list(range(cols)) self.__r = {} def __str__(self): d = { MinesGrid.MINE: 'X', 0: '.' } return "".join(map(str, (d[self[i]] if self[i] in d else self[i] for i in range(self.__cols)))) def __repr__(self): return f"Row(cols={self.__cols}, empty_cells={self.__empty_cells}, r={self.__r})" def __getitem__(self, k): return self.__r[k] if k in self.__r else 0 def __setitem__(self, k, v): if k not in self.__r: if k not in self.__empty_cells: raise ValueError(f"{k} is not in a valid range.") if v == MinesGrid.MINE: self.__empty_cells.remove(k) self.__r[k] = v @property def number_empty(self): return len(self.__empty_cells) @property def random_cell(self): if l := self.number_empty: r = randrange(l) return self.__empty_cells[r] return None class Empty: def __getitem__(self, k): return 0 def __init__(self, rows, cols, mines): if rows <= 0 or cols <= 0: raise ValueError(f"rows and columns need to be positive integers. rows={rows}, cols={cols}") if mines > rows * cols: raise ValueError(f"Too many mines: {mines}") self.__rows = rows self.__cols = cols self.__empty = rows * cols self.__a = {} # This a a dict of Row objects self.__empty_row = MinesGrid.Empty() for _ in range(mines): self.__place_mine() def __repr__(self): return f"MinesGrid(rows={self.__rows}, cols={self.__cols}, empty={self.__empty}, rows={self.__a}" def __str__(self): empty = "." * self.__cols return "\n".join(empty if r not in self.__a else str(self.__a[r]) for r in range(self.__rows)) def __place_mine(self): if self.__empty: r = randrange(self.__rows) while r in self.__a and self.__a[r].number_empty == 0: r = (r + 1) % self.__cols if r not in self.__a: self.__a[r] = MinesGrid.Row(self.__cols) c = self.__a[r].random_cell self.__a[r][c] = MinesGrid.MINE self.__update_counts(r, c) self.__empty -= 1 def __update_counts(self, r, c): t = ( (-1,-1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)) for t1, t2 in t: if 0 <= r+t1 < self.__rows and 0 <= c+t2 < self.__cols: u_r, u_c = r+t1, c+t2 if u_r not in self.__a: self.__a[u_r] = MinesGrid.Row(self.__cols) if self.__a[u_r][u_c] != MinesGrid.MINE: self.__a[u_r][u_c] += 1 def __getitem__(self, k): return self.__a[k] if k in self.__a else self.__empty_row def __setitem__(self, k, v): self.__a[k] = v if __name__ == "__main__": tests = ((16, 12, 4), (8, 8, 5), (5,5, 20)) for r,c,m in tests: o = MinesGrid(r, c, m) print(f"{r}X{c} Grid with {m} mines:\n") print(o) print("")