Skip to content

Instantly share code, notes, and snippets.

@purpleP
Last active May 9, 2017 13:18
Show Gist options
  • Save purpleP/97197cb2315592a75651289c7c7b29f8 to your computer and use it in GitHub Desktop.
Save purpleP/97197cb2315592a75651289c7c7b29f8 to your computer and use it in GitHub Desktop.

If constructing an object is entagled with different cases and conditions it's better to use factory. That's not the case here.

Instead of this.

def make_board(mines, size):
    '''function that uses my created Board methods to create the playing board'''
    board = Board(tuple([tuple([Cell(True,True,True) for i in range(size+1)]) for j in range(size+1)]))
    open_pos = list(range(size-1)*(size-1))
    for i in range(mines):
        new_pos = random.choice(open_pos) #randomly select from open positions
        open_pos.remove(new_pos) # take that new position out of the open one
        (row_coord,col_coord) = (new_pos % 9, new_pos // 9) # mod and floor div
        board.put_mine(row_coord,col_coord) #put the mine in the new random location
    return board

You can do this. Notice also how I've transformed your code from imperative into declarative and used prefer composition over inheritance by creating self.cells.

def chunks(sequence, n):
    iters = (iter(iterable),) * n
    return zip(*iters)

class Board:
    '''class that creates the playing board'''

    def __init__(self, mines_count, height, width): #initializing
        size = height * width
        mines = chain(repeat(True, mines_count), repeat(False, size - mines_count))
        mines = rnd.shuffle(mines)
        cells = (Cell(is_mine) for is_mine in mines)
        self.cells = chunks(cells, width)
        self.playing = True

Use default values in initializer of Cell

class Cell(object):
    """a class to deal with individual cells"""
    def __init__(self, can_see, flagged, is_mine): #initializing Cell class
        self.can_see = not can_see
        self.flagged = not flagged
        self.is_mine = is_mine

class Cell(object):
    '''a class to deal with individual cells'''
    def __init__(self, is_mine, visible=False, flagged=False): #initializing Cell class
        self.visible = visible
        self.flagged = flagged
        self.is_mine = is_mine

And is_solved can be expressed much shortly and more readable

    def is_solved(self):
        for row in self:
            for cell in row:
                if not(cell.can_see or cell.flagged):
                    return False
        return True
def is_solved(self):
        return all(c.visible and c.flagged for c in chain.from_iterable(self.cells))

No need for parenthesis in sequence unpacking and in conditionals too.

for col_coord, cell in enumerate(row):
...
if cell.is_mine and not cell.flagged:

You're not finding neighbours they just are. Using iterools

def find_neighbors(self, row_coord,col_coord):
    surr = ((-1,-1), (-1,0), (-1,1), (0,-1), (0,1), (1,-1), (1,0), (1,1))
    y = ((row_coord + surr_row, col_coord + surr_col) for (surr_row,surr_col) in surr)
    return y
    
def neighbors(self, row, col):
    return (
        self.cells[row + x][col + y]
        for x, y in product((-1, 0, 1), repeat=2)
        if (x, y) != (0, 0)
        and 0 <= row + x <= self.width
        and 0 <= col + y <= self.height
    ) 

And now this

    def count_surroundings(self,row_coord,col_coord):
        count = 0
        for (surr_row,surr_col) in self.find_neighbors(row_coord,col_coord):
            if (self.is_in_range(surr_row,surr_col) and self[surr_row][surr_col].is_mine):
                count += 1
        return count

Becomes oneliners

    def surrounding_mines_count(self,row_coord,col_coord):
        return sum(cell.is_mine for cell in self.neighbors(row, col))
        
    def mines_left(self):
        return sum(c.is_mine and not c.flagged for c in chain.from_iterable(self.cells))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment