The Board

gaming_new_game.bmp
The board at the start of a game

The initial state of the board is shown above. All is hidden, a morass of mystery, intrigue, and danger. Most squares are harmless, but some hide a bomb. Your goal as a player is to find those bombs.

The first thing is to set up the screen structures.

A TileGrid is used for the game board, along with a spritesheet that is loaded from a file. Read more about TileGrid, spritesheets, and palettes in this guide.

Download: file
NUMBER_OF_BOMBS = 15

# Board pieces

OPEN0 = 0
OPEN1 = 1
OPEN2 = 2
OPEN3 = 3
OPEN4 = 4
OPEN5 = 5
OPEN6 = 6
OPEN7 = 7
OPEN8 = 8
BLANK = 9
BOMBDEATH = 10
BOMBFLAGGED = 11
BOMBMISFLAGGED = 12
BOMBQUESTION = 13
BOMB = 14

sprite_sheet, palette = adafruit_imageload.load("/SpriteSheet.bmp",
                                                bitmap=displayio.Bitmap,
                                                palette=displayio.Palette)

display = board.DISPLAY
group = displayio.Group(scale=1, max_size=5)
touchscreen = adafruit_touchscreen.Touchscreen(board.TOUCH_XL, board.TOUCH_XR,
                                               board.TOUCH_YD, board.TOUCH_YU,
                                               calibration=((9000, 59000),
                                                            (8000, 57000)),
                                               size=(display.width, display.height))
tilegrid = displayio.TileGrid(sprite_sheet, pixel_shader=palette,
                              width=20, height=15,
                              tile_height=16, tile_width=16,
                              default_tile=BLANK)
group.append(tilegrid)



display.show(group)

The code above handles what's on the screen. That's what the player sees, but we also need to know where the bombs are and how many bombs are next to each square. There aren't many options, so a byte array works fine. There are two get/set functions, so we can access it using the same x/y coordinates that we use with the tilegrid.

Download: file
board_data = bytearray(b'\x00' * 300)

#pylint:disable=redefined-outer-name
def get_data(x, y):
    return board_data[y * 20 + x]

def set_data(x, y, value):
    board_data[y * 20 + x] = value
#pylint:disable=redefined-outer-name

Next are two functions to initialize the bytearray. The first randomly places bombs. The loop is used to repeated generate a random square until a clear one is found.

Download: file
def seed_bombs(how_many):
    for _ in range(how_many):
        while True:
            bomb_x = randint(0, 19)
            bomb_y = randint(0, 14)
            if get_data(bomb_x, bomb_y) == 0:
                set_data(bomb_x, bomb_y, 14)
                break

The next function sets the counts in squares adjacent to the bombs. It scans for bombs and when it finds one it increments the value (initialized to 0, see above) in each of the eight squares surrounding the bomb. Of course, if it's another bomb, it's skipped. There's code in there to ignore any squares that are outside the board. This is an issue when a bomb is along the edge of the board.

Download: file
def compute_counts():
    """For each bomb, increment the count in each non-bomb square around it"""
    for y in range(15):
        for x in range(20):
            if get_data(x, y) != 14:
                continue                  # keep looking for bombs
            for dx in (-1, 0, 1):
                if x + dx < 0 or x + dx >= 20:
                    continue              # off screen
                for dy in (-1, 0, 1):
                    if y + dy < 0 or y + dy >= 15:
                        continue          # off screen
                    count = get_data(x + dx, y + dy)
                    if count == 14:
                        continue          # don't process bombs
                    set_data(x + dx, y + dy, count + 1)

To start a game, the board must be initialized using the above functions. This is handled by the reset_board function:

Download: file
def reset_board():
    for x in range(20):
        for y in range(15):
            tilegrid[x, y] = BLANK
            set_data(x, y, 0)
    seed_bombs(NUMBER_OF_BOMBS)
    compute_counts()
This guide was first published on Aug 09, 2019. It was last updated on Aug 09, 2019. This page (The Board) was last updated on Sep 17, 2019.