Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 17 additions & 24 deletions Metro/Metro_RP2350_Minesweeper/code.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ def update_ui():

buf = array.array("b", [0] * 4)
waiting_for_release = False
chord_selected = False
left_button = right_button = False
mouse_coords = (display.width // 2, display.height // 2)

Expand Down Expand Up @@ -231,41 +232,21 @@ def hide_group(group):

menus = (reset_menu, difficulty_menu)

# Mouse state
last_left_button_state = 0
last_right_button_state = 0
left_button_pressed = False
right_button_pressed = False

# main loop
while True:
update_ui()
# update cursor position, and check for clicks
buttons = mouse.update()
mouse.update()
buttons = mouse.pressed_btns

# Extract button states
if buttons is None:
if buttons is None or buttons == ():
left_button = 0
right_button = 0
else:
left_button = 1 if 'left' in buttons else 0
right_button = 1 if 'right' in buttons else 0

# Detect button presses
if left_button == 1 and last_left_button_state == 0:
left_button_pressed = True
elif left_button == 0 and last_left_button_state == 1:
left_button_pressed = False

if right_button == 1 and last_right_button_state == 0:
right_button_pressed = True
elif right_button == 0 and last_right_button_state == 1:
right_button_pressed = False

# Update button states
last_left_button_state = left_button
last_right_button_state = right_button

mouse_coords = (mouse_tg.x, mouse_tg.y)

if waiting_for_release and not left_button and not right_button:
Expand All @@ -282,11 +263,23 @@ def hide_group(group):
else:
# process gameboard click if no menu
ms_board = game_logic.game_board

if left_button and right_button and not chord_selected:
chord_coords = ((mouse_tg.x - ms_board.x) // 16, (mouse_tg.y - ms_board.y) // 16)
chord_selected = game_logic.square_chord_highlight(chord_coords)
if chord_selected:
waiting_for_release = True

if (ms_board.x <= mouse_tg.x <= ms_board.x + game_logic.grid_width * 16 and
ms_board.y <= mouse_tg.y <= ms_board.y + game_logic.grid_height * 16 and
not waiting_for_release):

coords = ((mouse_tg.x - ms_board.x) // 16, (mouse_tg.y - ms_board.y) // 16)
if right_button:
if chord_selected:
chord_selected = False
game_logic.square_chord_highlight(chord_coords, False)
game_logic.square_chorded(chord_coords)
elif right_button:
game_logic.square_flagged(coords)
elif left_button:
if not game_logic.square_clicked(coords):
Expand Down
81 changes: 79 additions & 2 deletions Metro/Metro_RP2350_Minesweeper/gamelogic.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ def _set_data(self, x, y, value):
self._board_data[y * self.grid_width + x] = value

def _get_data(self, x, y):
if x < 0 or x >= self.grid_width or y < 0 or y >= self.grid_height:
return None # out of bounds, do nothing
return self._board_data[y * self.grid_width + x]

def _set_board(self, x, y, value):
Expand All @@ -102,6 +104,8 @@ def _set_board(self, x, y, value):
def _get_board(self, x, y):
if not isinstance(self.game_board, TileGrid):
raise ValueError("Game board not initialized")
if x < 0 or x >= self.grid_width or y < 0 or y >= self.grid_height:
return None # out of bounds, do nothing
return self.game_board[x, y] # pylint: disable=unsubscriptable-object

def _compute_counts(self):
Expand Down Expand Up @@ -165,6 +169,77 @@ def square_flagged(self, coords):
break
return True

def square_chorded(self, coords):
if self._status in (STATUS_WON, STATUS_LOST):
return False

x, y = coords
if x < 0 or x >= self.grid_width or y < 0 or y >= self.grid_height:
return True # out of bounds, do nothing

value = self._get_board(x, y)

if value not in (OPEN1, OPEN2, OPEN3, OPEN4, OPEN5, OPEN6, OPEN7, OPEN8):
return True # Nothing to do if not an open numbered square

# Pre-compute valid neighbors
neighbors = [
(nx, ny)
for nx in range(x - 1, x + 2)
for ny in range(y - 1, y + 2)
if (0 <= nx < self.grid_width
and 0 <= ny < self.grid_height
and not (nx == x and ny == y))
]

# Count flagged neighbors
flags = sum(1 for nx, ny in neighbors if self._get_board(nx, ny) == FLAG)

if flags != value:
return True # not enough flags, do nothing

# Uncover all non-flagged neighbors
for nx, ny in neighbors:
if self._get_board(nx, ny) != FLAG:
if not self.square_clicked((nx, ny)):
return False # lost

return True

def square_chord_highlight(self, coords, highlight=True):
if self._status in (STATUS_WON, STATUS_LOST):
return False

x, y = coords
if x < 0 or x >= self.grid_width or y < 0 or y >= self.grid_height:
return False # out of bounds, do nothing

value = self._get_board(x, y)

if value not in (OPEN1, OPEN2, OPEN3, OPEN4, OPEN5, OPEN6, OPEN7, OPEN8):
return False # Nothing to do if not an open numbered square

# Pre-compute valid neighbors
neighbors = [
(nx, ny)
for nx in range(x - 1, x + 2)
for ny in range(y - 1, y + 2)
if (0 <= nx < self.grid_width
and 0 <= ny < self.grid_height
and not (nx == x and ny == y))
]

# Highlight all non-flagged squares around here
for nx, ny in neighbors:
if highlight:
if self._get_board(nx, ny) == BLANK:
self._set_board(nx, ny,MINE_QUESTION_OPEN)
else:
if self._get_board(nx, ny) == MINE_QUESTION_OPEN:
self._set_board(nx, ny, BLANK)

return True

def square_clicked(self, coords):
x, y = coords

Expand All @@ -178,7 +253,7 @@ def square_clicked(self, coords):
if self._start_time is None:
self._start_time = ticks_ms()

if self._get_board(x, y) != FLAG:
if self._get_board(x, y) not in (FLAG, None):
under_the_tile = self._get_data(x, y)
if under_the_tile == MINE:
self._set_data(x, y, MINE_CLICKED)
Expand Down Expand Up @@ -215,7 +290,9 @@ def check_for_win(self):
# first make sure everything has been explored and decided
for x in range(self.grid_width):
for y in range(self.grid_height):
if self._get_board(x, y) == BLANK or self._get_board(x, y) == MINE_QUESTION:
if self._get_board(x, y) == BLANK or \
self._get_board(x, y) == MINE_QUESTION or \
self._get_board(x, y) == MINE_QUESTION_OPEN:
return None # still ignored or question squares
# then check for mistagged bombs
for x in range(self.grid_width):
Expand Down