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.
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() 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.root_group = 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.
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.
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.
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:
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()
Text editor powered by tinymce.