Created
March 4, 2019 17:19
-
-
Save mobyjames/17e334b8844acea7864841c4c3b75beb to your computer and use it in GitHub Desktop.
Adafruit Trellis Minesweeper
This file contains 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 characters
# Mine Puzzle Game | |
# Created by James Jacoby, December 2018 | |
# | |
# A mine clearing game loosely based on minesweeper | |
# | |
# HOW TO PLAY: | |
# | |
# Press a key to clear a space | |
# If it's a mine, you lose | |
# Otherwise, the adjacent spaces will change color to indicate the number | |
# of surrounding mines neaby. If it doesn't change- it's a mine for sure! | |
# Try to clear all the non-mine spaces! | |
# Thump to reset board | |
# | |
# 0: mint | |
# 1: dark green | |
# 2: dark blue | |
# 3: purple | |
# 4: dark red | |
# 5 or more: medium red | |
# | |
# IDEAS TO TRY: | |
# | |
# Change color codes to suite your eyes | |
# Add more risk levels if you feel like memorizing more colors | |
# Change difficulty level by adjusting percentage of mines | |
# Add other fun animations for victory, failure or resetting the board | |
# Add a way to flag a mine | |
# | |
import time | |
import math | |
import random | |
import adafruit_trellism4 | |
import adafruit_adxl34x | |
import board | |
import busio | |
trellis = adafruit_trellism4.TrellisM4Express() | |
i2c = busio.I2C(board.ACCELEROMETER_SCL, board.ACCELEROMETER_SDA) | |
accelerometer = adafruit_adxl34x.ADXL345(i2c) | |
accelerometer.enable_motion_detection(threshold=250) | |
UNKNOWN = 0x000000 | |
MINE = 0xFF0000 | |
CLEAR = 0x315612 | |
ONE = 0x001100 | |
TWO = 0x000011 | |
THREE = 0xDD00AA | |
FOUR = 0x110000 | |
FIVE = 0xAA0000 | |
STATE_PLAY = 0 | |
STATE_FAIL = 1 | |
STATE_VICTORY = 2 | |
w = 8 | |
h = 4 | |
percent = 0.2 | |
mines = [0 for _ in range(32)] | |
key_state = [0 for _ in range(32)] | |
risks = [CLEAR, ONE, TWO, THREE, FOUR, FIVE, FIVE, FIVE, FIVE] | |
total_mines = 0 | |
game_state = STATE_PLAY | |
current_press = set() | |
victory_flash = True | |
def setPixel(index, color): | |
global key_state | |
key_state[index] = color | |
y = math.floor(index / 8) | |
x = index % 8 | |
trellis.pixels[x, y] = color | |
def reset(): | |
global total_mines | |
global game_state | |
global mines | |
total_mines = 0 | |
for i in range(8): | |
sweep(i) | |
time.sleep(0.05) | |
for i in range(32): | |
setPixel(i, UNKNOWN) | |
mines[i] = random.random() <= percent | |
if mines[i]: | |
total_mines += 1 | |
game_state = STATE_PLAY | |
def mineAt(x, y): | |
if x < 0 or x >= w: | |
return False | |
elif y < 0 or y >= h: | |
return False | |
else: | |
index = y * 8 + x | |
return mines[index] | |
def showRiskForSpace(x, y): | |
if x < 0 or x >= w or y < 0 or y >= h: | |
return | |
index = y * 8 + x | |
if mines[index]: # don't show clue for for-sure mines | |
return | |
count = 0 | |
if mineAt(x-1, y-1): | |
count +=1 | |
if mineAt(x, y-1): | |
count +=1 | |
if mineAt(x+1, y-1): | |
count +=1 | |
if mineAt(x-1, y): | |
count +=1 | |
if mineAt(x+1, y): | |
count +=1 | |
if mineAt(x-1, y+1): | |
count +=1 | |
if mineAt(x, y+1): | |
count +=1 | |
if mineAt(x+1, y+1): | |
count +=1 | |
if count == 0: # keep going to clear obvious zero-risk spaces | |
clearSpace(x, y) | |
color = risks[count] | |
setPixel(index, color) | |
def clearSpace(x, y): | |
index = y * 8 + x | |
current = key_state[index] | |
if current != UNKNOWN: # can't press spaces with known values | |
return | |
elif mines[index]: # you dead | |
explodeTheBoard() | |
else: | |
setPixel(index, CLEAR) | |
showRiskForSpace(x-1, y-1) | |
showRiskForSpace(x, y-1) | |
showRiskForSpace(x+1, y-1) | |
showRiskForSpace(x-1, y) | |
showRiskForSpace(x+1, y) | |
showRiskForSpace(x-1, y+1) | |
showRiskForSpace(x, y+1) | |
showRiskForSpace(x+1, y+1) | |
checkVictory() | |
def explodeTheBoard(): | |
for i in range(32): | |
setPixel(i, MINE) | |
def showVictory(flashOn): | |
for i in range(32): | |
if mines[i]: | |
if flashOn: | |
setPixel(i, MINE) | |
else: | |
setPixel(i, 0) | |
def checkVictory(): | |
global total_mines | |
global game_state | |
remaining = 0 | |
for i in range(32): | |
if key_state[i] == UNKNOWN: | |
remaining += 1 | |
if remaining == total_mines: | |
game_state = STATE_VICTORY | |
showVictory(True) | |
def sweep(col): | |
for i in range(32): | |
x = i % 8 | |
if x == col: | |
setPixel(i, MINE) | |
elif x < col: | |
setPixel(i, 0) | |
reset() | |
while True: | |
pressed = set(trellis.pressed_keys) | |
if game_state == STATE_PLAY: | |
for press in pressed: | |
if press: | |
x, y = press | |
index = (y * 8) + x | |
clearSpace(x, y) | |
elif game_state == STATE_VICTORY: | |
showVictory(victory_flash) | |
victory_flash = not victory_flash | |
if accelerometer.events['motion'] == True: | |
reset() | |
time.sleep(0.08) | |
current_press = pressed |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment