minesweeper.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import re
from itertools import product

# Top or bottom border, e.g. "+------+"
HORIZONTAL_BORDER = re.compile(r'''
    \+      # starts with +
    \-+     # any number of -
    \+      # ends with +
''', re.VERBOSE)

# Tile row, e.g. |   *  |
TILE_ROW = re.compile(r'''
    \|      # starts with |
    (\ |\*)+ # any number of ' ' or '*'
    \|      # ends with |
''', re.VERBOSE)


def surrounding_tiles(row, col):
    """
    Generate coordinates of all tiles surrounding (row, col),
    excluding the tile itself
    """
    return (
        (row+i, col+j)
        for (i, j) in product((1, 0, -1), repeat=2)
        if i or j       # exclude (0, 0) which is itself
    )


def board(inp):
    if not all(len(row) == len(inp[0]) for row in inp):
        raise ValueError("Rows must be of equal length")

    if not all((
        HORIZONTAL_BORDER.match(inp[0]),
        HORIZONTAL_BORDER.match(inp[-1]),
        all(TILE_ROW.match(row) for row in inp[1:-1])
    )):
        raise ValueError("Invalid board format")

    # Create a mutable structure that can be modified as we count mines
    tiles = [list(row) for row in inp]

    # Just iterate over the inner board -
    # the edges are handy for keeping indexes valid :)
    row_range = range(1, len(tiles)-1)
    col_range = range(1, len(tiles[0])-1)

    def increment_tile(row, col):
        value = tiles[row][col]
        if value == ' ':
            tiles[row][col] = '1'
        elif value.isdigit():
            tiles[row][col] = str(int(value)+1)

    # Find mines and increment surrounding tiles
    for row in row_range:
        for col in col_range:
            if tiles[row][col] == '*':
                for (r, c) in surrounding_tiles(row, col):
                    increment_tile(r, c)

    return [''.join(row) for row in tiles]

Comments

This version searches for mines and increments the cells around them. Should perform better where there are fewer mines than spaces (as would be expected)

helenst commented 27 May 2016 at 09:38 UTC

You're not logged in right now. Please login via GitHub to comment