# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
-#.idea/
+.idea/
--- /dev/null
+import pygame.event
+
+from setup import *
+from grid import Grid
+
+
+class Game:
+
+ def __init__(self):
+ self.grid = Grid(20, 20, 50)
+
+ self.game_over = False
+
+ def update(self, delta):
+ for event in pygame.event.get():
+ if event.type == pygame.QUIT:
+ return COMMAND_EXIT
+
+ mouse_pos = pygame.mouse.get_pos()
+ mouse_button = pygame.mouse.get_pressed()
+ if self.grid.update(delta, mouse_pos, mouse_button):
+ return COMMAND_LOSE
+ if self.grid.win():
+ return COMMAND_WIN
+
+ return COMMAND_NONE
+
+ def draw(self, screen):
+ screen.fill(BLACK)
+ self.grid.draw(screen)
--- /dev/null
+import random
+from setup import *
+
+
+class Grid:
+
+ def __init__(self, length, height, bomb_count):
+ self.length, self.height = length, height
+ self.grid = [[Cell(j, i) for j in range(self.length)] for i in range(self.height)]
+
+ self.bomb_count = bomb_count
+ self.place_bombs(self.bomb_count)
+
+ self.mouse_cooldown = 0
+
+ for row in self.grid:
+ for cell in row:
+ neighbors = []
+ for i in range(-1, 2):
+ for j in range(-1, 2):
+ x = int(cell.position.x // Cell.cell_size + i)
+ y = int(cell.position.y // Cell.cell_size + j)
+ if 0 <= y < self.height and 0 <= x < self.length and not (i == 0 and j == 0):
+ neighbors.append(self.grid[y][x])
+ cell.give_number(neighbors)
+
+ def update(self, delta, mouse_pos, mouse_button):
+ if self.mouse_cooldown > 0:
+ self.mouse_cooldown -= delta
+ return False
+
+ for row in self.grid:
+ for cell in row:
+ if cell.position.x <= mouse_pos[0] <= cell.position.x + Cell.cell_size and cell.position.y <= mouse_pos[1] <= cell.position.y + Cell.cell_size:
+ if mouse_button[0] == 1:
+ self.mouse_cooldown = 0.2
+ if cell.update(self.grid, self.height, self.length):
+ return True
+ elif mouse_button[2] == 1:
+ if not cell.discovered:
+ cell.flagged = not cell.flagged
+ self.mouse_cooldown = 0.2
+ return False
+
+ def win(self):
+ for row in self.grid:
+ for cell in row:
+ if not cell.is_bomb and not cell.discovered:
+ return False
+ return True
+
+ def draw(self, screen):
+ for row in self.grid:
+ for cell in row:
+ cell.draw(screen)
+
+ def place_bombs(self, bomb_count):
+ while bomb_count > 0:
+ x = random.randint(0, self.length - 1)
+ y = random.randint(0, self.height - 1)
+ if not self.grid[y][x].is_bomb:
+ self.grid[y][x].is_bomb = True
+ bomb_count -= 1
+
+
+class Cell:
+ cell_size = 25
+ font = pygame.font.SysFont("Arial", 20)
+
+ def __init__(self, x, y):
+ self.position = pygame.Vector2(x * self.cell_size, y * self.cell_size)
+ self.is_bomb = False
+ self.flagged = False
+ self.number = 0
+ self.discovered = False
+ self.color = GRAY
+ self.text = None
+
+ def update(self, grid, height, length):
+ if self.discovered or self.flagged:
+ return False
+ self.discovered = True
+ self.color = GREEN
+ if self.is_bomb:
+ self.color = RED
+ return True
+
+ if self.number == 0:
+ for i in range(-1, 2):
+ for j in range(-1, 2):
+ x = int(self.position.x // self.cell_size + i)
+ y = int(self.position.y // self.cell_size + j)
+ if 0 <= y < height and 0 <= x < length and not (i == 0 and j == 0):
+ if not grid[y][x].discovered and not grid[y][x].flagged:
+ grid[y][x].update(grid, height, length)
+
+ return False
+
+ def give_number(self, neighbors):
+ if self.is_bomb:
+ return
+ for neighbor in neighbors:
+ if neighbor.is_bomb:
+ self.number += 1
+
+ self.text = self.font.render(str(self.number), True, BLACK)
+
+ def draw(self, screen):
+ display_color = self.color
+ if self.flagged:
+ display_color = BLUE
+
+ pygame.draw.rect(screen, display_color, (self.position.x, self.position.y, self.cell_size, self.cell_size))
+ pygame.draw.rect(screen, BLACK, (self.position.x, self.position.y, self.cell_size, self.cell_size), 1)
+ if self.discovered and self.number > 0:
+ screen.blit(self.text, self.text.get_rect(
+ center=(self.position.x + self.cell_size / 2, self.position.y + self.cell_size / 2)))
--- /dev/null
+from setup import *
+from game import Game
+from menus import Lose, Win
+
+def main():
+ scene = Game()
+ is_running = True
+ delta = 0
+ while is_running:
+ status = scene.update(delta)
+ scene.draw(screen)
+
+ if status == COMMAND_EXIT:
+ is_running = False
+ elif status == COMMAND_RESTART:
+ scene = Game()
+ elif status == COMMAND_WIN:
+ scene = Win(screen)
+ elif status == COMMAND_LOSE:
+ scene = Lose(screen)
+
+ pygame.display.update()
+ delta = clock.tick(60)/1000
+
+if __name__ == "__main__":
+ main()
--- /dev/null
+from setup import *
+
+
+class Menu:
+ title = pygame.font.SysFont("Arial", 30)
+ subtitle = pygame.font.SysFont("Arial", 20)
+ padding = 10
+
+ def __init__(self, screen, title, subtitle, text_color=RED):
+ self.bg = screen.copy()
+ self.titleText = self.title.render(title, True, text_color)
+ self.subtitleText = self.subtitle.render(subtitle, True, text_color)
+
+ def update(self, delta):
+ for event in pygame.event.get():
+ if event.type == pygame.QUIT:
+ return COMMAND_EXIT
+ elif event.type == pygame.KEYDOWN:
+ if event.key == pygame.K_r:
+ return COMMAND_RESTART
+ return COMMAND_NONE
+
+ def draw(self, screen):
+ screen.blit(self.bg, (0, 0))
+ titleRect = self.titleText.get_rect(center=(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2))
+ subtitleRect = self.subtitleText.get_rect(center=(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 + 50))
+ boxRect = pygame.Rect(min(titleRect.x, subtitleRect.x) - self.padding,
+ min(titleRect.y, subtitleRect.y) - self.padding,
+ max(titleRect.width, subtitleRect.width) + self.padding * 2,
+ titleRect.height / 2 + subtitleRect.height / 2 + abs(
+ titleRect.y - subtitleRect.y) + self.padding * 2)
+ pygame.draw.rect(screen, BLACK, boxRect)
+ pygame.draw.rect(screen, GRAY, boxRect, 4)
+ screen.blit(self.titleText, titleRect)
+ screen.blit(self.subtitleText, subtitleRect)
+
+
+class Lose(Menu):
+
+ def __init__(self, screen):
+ super().__init__(screen, "You Lose!", "Press R to restart")
+
+
+class Win(Menu):
+ def __init__(self, screen):
+ super().__init__(screen, "You Win!", "Press R to play again", GREEN)
--- /dev/null
+import pygame
+
+pygame.init()
+SCREEN_WIDTH = 800
+SCREEN_HEIGHT = 600
+screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
+pygame.display.set_caption("Minesweeper")
+clock = pygame.time.Clock()
+
+RED = (255, 0, 0)
+GREEN = (0, 255, 0)
+BLUE = (0, 0, 255)
+BLACK = (0, 0, 0)
+WHITE = (255, 255, 255)
+GRAY = (128, 128, 128)
+
+
+COMMAND_EXIT = 0
+COMMAND_RESTART = 1
+COMMAND_WIN = 2
+COMMAND_LOSE = 3
+COMMAND_NONE = 4
\ No newline at end of file