Skip to content

Commit 11e2920

Browse files
authored
Merge pull request #790 from dastels/mindsweep
Add minesweeper code
2 parents 1bcc622 + 4e72f9d commit 11e2920

3 files changed

Lines changed: 253 additions & 2 deletions

File tree

Minesweep/SpriteSheet.bmp

2.16 KB
Binary file not shown.

Minesweep/code.py

Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
"""
2+
PyPortal based countdown of days until Halloween.
3+
4+
Adafruit invests time and resources providing this open source code.
5+
Please support Adafruit and open source hardware by purchasing
6+
products from Adafruit!
7+
8+
Written by Dave Astels for Adafruit Industries
9+
Copyright (c) 2019 Adafruit Industries
10+
Licensed under the MIT license.
11+
12+
All text above must be included in any redistribution.
13+
"""
14+
15+
import time
16+
from random import seed, randint
17+
import board
18+
import digitalio
19+
import displayio
20+
import audioio
21+
import adafruit_imageload
22+
import adafruit_touchscreen
23+
24+
seed(int(time.monotonic()))
25+
26+
# Set up audio
27+
speaker_enable = digitalio.DigitalInOut(board.SPEAKER_ENABLE)
28+
speaker_enable.switch_to_output(False)
29+
if hasattr(board, 'AUDIO_OUT'):
30+
audio = audioio.AudioOut(board.AUDIO_OUT)
31+
elif hasattr(board, 'SPEAKER'):
32+
audio = audioio.AudioOut(board.SPEAKER)
33+
else:
34+
raise AttributeError('Board does not have a builtin speaker!')
35+
36+
37+
NUMBER_OF_BOMBS = 15
38+
39+
# Board pieces
40+
41+
OPEN0 = 0
42+
OPEN1 = 1
43+
OPEN2 = 2
44+
OPEN3 = 3
45+
OPEN4 = 4
46+
OPEN5 = 5
47+
OPEN6 = 6
48+
OPEN7 = 7
49+
OPEN8 = 8
50+
BLANK = 9
51+
BOMBDEATH = 10
52+
BOMBFLAGGED = 11
53+
BOMBMISFLAGGED = 12
54+
BOMBQUESTION = 13
55+
BOMB = 14
56+
57+
sprite_sheet, palette = adafruit_imageload.load("/SpriteSheet.bmp",
58+
bitmap=displayio.Bitmap,
59+
palette=displayio.Palette)
60+
61+
display = board.DISPLAY
62+
group = displayio.Group(scale=1, max_size=5)
63+
touchscreen = adafruit_touchscreen.Touchscreen(board.TOUCH_XL, board.TOUCH_XR,
64+
board.TOUCH_YD, board.TOUCH_YU,
65+
calibration=((9000, 59000),
66+
(8000, 57000)),
67+
size=(display.width, display.height))
68+
tilegrid = displayio.TileGrid(sprite_sheet, pixel_shader=palette,
69+
width=20, height=15,
70+
tile_height=16, tile_width=16,
71+
default_tile=BLANK)
72+
group.append(tilegrid)
73+
74+
75+
76+
display.show(group)
77+
78+
board_data = bytearray(b'\x00' * 300)
79+
80+
#pylint:disable=redefined-outer-name
81+
def get_data(x, y):
82+
return board_data[y * 20 + x]
83+
84+
def set_data(x, y, value):
85+
board_data[y * 20 + x] = value
86+
#pylint:disable=redefined-outer-name
87+
88+
def seed_bombs(how_many):
89+
for _ in range(how_many):
90+
while True:
91+
bomb_x = randint(0, 19)
92+
bomb_y = randint(0, 14)
93+
if get_data(bomb_x, bomb_y) == 0:
94+
set_data(bomb_x, bomb_y, 14)
95+
break
96+
97+
def compute_counts():
98+
"""For each bomb, increment the count in each non-bomb square around it"""
99+
for y in range(15):
100+
for x in range(20):
101+
if get_data(x, y) != 14:
102+
continue # keep looking for bombs
103+
for dx in (-1, 0, 1):
104+
if x + dx < 0 or x + dx >= 20:
105+
continue # off screen
106+
for dy in (-1, 0, 1):
107+
if y + dy < 0 or y + dy >= 15:
108+
continue # off screen
109+
count = get_data(x + dx, y + dy)
110+
if count == 14:
111+
continue # don't process bombs
112+
set_data(x + dx, y + dy, count + 1)
113+
114+
def reveal():
115+
for x in range(20):
116+
for y in range(15):
117+
if tilegrid[x, y] == BOMBFLAGGED and get_data(x, y) != BOMB:
118+
tilegrid[x, y] = BOMBMISFLAGGED
119+
else:
120+
tilegrid[x, y] = get_data(x, y)
121+
122+
#pylint:disable=too-many-nested-blocks
123+
def expand_uncovered(start_x, start_y):
124+
number_uncovered = 1
125+
stack = [(start_x, start_y)]
126+
while len(stack) > 0:
127+
x, y = stack.pop()
128+
if tilegrid[x, y] == BLANK:
129+
under_the_tile = get_data(x, y)
130+
if under_the_tile <= OPEN8:
131+
tilegrid[x, y] = under_the_tile
132+
number_uncovered += 1
133+
if under_the_tile == OPEN0:
134+
for dx in (-1, 0, 1):
135+
if x + dx < 0 or x + dx >= 20:
136+
continue # off screen
137+
for dy in (-1, 0, 1):
138+
if y + dy < 0 or y + dy >= 15:
139+
continue # off screen
140+
if dx == 0 and dy == 0:
141+
continue # don't process where the bomb
142+
stack.append((x + dx, y + dy))
143+
return number_uncovered
144+
#pylint:enable=too-many-nested-blocks
145+
146+
def check_for_win():
147+
"""Check for a complete, winning game. That's one with all squares uncovered
148+
and all bombs correctly flagged, with no non-bomb squares flaged.
149+
"""
150+
# first make sure everything has been explored and decided
151+
for x in range(20):
152+
for y in range(15):
153+
if tilegrid[x, y] == BLANK or tilegrid[x, y] == BOMBQUESTION:
154+
return None #still ignored or question squares
155+
# then check for mistagged bombs
156+
for x in range(20):
157+
for y in range(15):
158+
if tilegrid[x, y] == BOMBFLAGGED and get_data(x, y) != BOMB:
159+
return False #misflagged bombs, not done
160+
return True #nothing unexplored, and no misflagged bombs
161+
162+
#pylint:disable=too-many-branches
163+
# This could be broken apart but I think it's more understandable
164+
# with it all in one place
165+
def play_a_game():
166+
number_uncovered = 0
167+
touch_x = -1
168+
touch_y = -1
169+
touch_time = 0
170+
wait_for_release = False
171+
while True:
172+
now = time.monotonic()
173+
if now >= touch_time:
174+
touch_time = now + 0.2
175+
# process touch
176+
touch_at = touchscreen.touch_point
177+
if touch_at is None:
178+
wait_for_release = False
179+
else:
180+
if wait_for_release:
181+
continue
182+
wait_for_release = True
183+
touch_x = max(min([touch_at[0] // 16, 19]), 0)
184+
touch_y = max(min([touch_at[1] // 16, 14]), 0)
185+
if tilegrid[touch_x, touch_y] == BLANK:
186+
tilegrid[touch_x, touch_y] = BOMBQUESTION
187+
elif tilegrid[touch_x, touch_y] == BOMBQUESTION:
188+
tilegrid[touch_x, touch_y] = BOMBFLAGGED
189+
elif tilegrid[touch_x, touch_y] == BOMBFLAGGED:
190+
under_the_tile = get_data(touch_x, touch_y)
191+
if under_the_tile == 14:
192+
set_data(touch_x, touch_y, BOMBDEATH) #reveal a red bomb
193+
tilegrid[touch_x, touch_y] = BOMBDEATH
194+
return False #lost
195+
elif under_the_tile > OPEN0 and under_the_tile <= OPEN8:
196+
tilegrid[touch_x, touch_y] = under_the_tile
197+
elif under_the_tile == OPEN0:
198+
tilegrid[touch_x, touch_y] = BLANK
199+
number_uncovered += expand_uncovered(touch_x, touch_y)
200+
else: #something bad happened
201+
raise ValueError('Unexpected value on board')
202+
status = check_for_win()
203+
if status is None:
204+
continue
205+
return status
206+
#pylint:enable=too-many-branches
207+
208+
def reset_board():
209+
for x in range(20):
210+
for y in range(15):
211+
tilegrid[x, y] = BLANK
212+
set_data(x, y, 0)
213+
seed_bombs(NUMBER_OF_BOMBS)
214+
compute_counts()
215+
216+
def play_sound(file_name):
217+
board.DISPLAY.wait_for_frame()
218+
wavfile = open(file_name, "rb")
219+
wavedata = audioio.WaveFile(wavfile)
220+
speaker_enable.value = True
221+
audio.play(wavedata)
222+
return wavfile
223+
224+
def wait_for_sound_and_cleanup(wavfile):
225+
while audio.playing:
226+
pass
227+
wavfile.close()
228+
speaker_enable.value = False
229+
230+
def win():
231+
print('You won')
232+
wait_for_sound_and_cleanup(play_sound('win.wav'))
233+
234+
def loose():
235+
print('You lost')
236+
wavfile = play_sound('loose.wav')
237+
for _ in range(10):
238+
tilegrid.x = randint(-2, 2)
239+
tilegrid.y = randint(-2, 2)
240+
display.refresh_soon()
241+
display.wait_for_frame()
242+
tilegrid.x = 0
243+
tilegrid.y = 0
244+
wait_for_sound_and_cleanup(wavfile)
245+
246+
while True:
247+
reset_board()
248+
if play_a_game():
249+
win()
250+
else:
251+
reveal()
252+
loose()
253+
time.sleep(5.0)

Twitter_API/code.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,6 @@ def get_bearer_token():
6262
json_path=(0, 'text'),
6363
status_neopixel=board.NEOPIXEL,
6464
default_bg=cwd + '/twitter_background.bmp',
65-
# external_spi=spi,
66-
# esp=esp,
6765
text_font=cwd+'/fonts/Helvetica-Bold-16.bdf',
6866
text_position=(20, 60),
6967
text_color=0xFFFFFF,

0 commit comments

Comments
 (0)