]> Skullheadx's Git Forge - Minesweeper.git/commitdiff
minesweeper
authorSkullheadx <admonty1@gmail.com>
Fri, 10 Mar 2023 01:09:08 +0000 (20:09 -0500)
committerSkullheadx <admonty1@gmail.com>
Fri, 10 Mar 2023 01:09:08 +0000 (20:09 -0500)
.gitignore
game.py [new file with mode: 0644]
grid.py [new file with mode: 0644]
main.py [new file with mode: 0644]
menus.py [new file with mode: 0644]
setup.py [new file with mode: 0644]

index d9005f2cc7fc4e65f14ed5518276007c08cf2fd0..3eb56cb1b2b440b4f8be065c26fb0972fe724648 100644 (file)
@@ -149,4 +149,4 @@ cython_debug/
 #  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/
diff --git a/game.py b/game.py
new file mode 100644 (file)
index 0000000..d59d3f0
--- /dev/null
+++ b/game.py
@@ -0,0 +1,30 @@
+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)
diff --git a/grid.py b/grid.py
new file mode 100644 (file)
index 0000000..5a43186
--- /dev/null
+++ b/grid.py
@@ -0,0 +1,117 @@
+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)))
diff --git a/main.py b/main.py
new file mode 100644 (file)
index 0000000..af94832
--- /dev/null
+++ b/main.py
@@ -0,0 +1,26 @@
+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()
diff --git a/menus.py b/menus.py
new file mode 100644 (file)
index 0000000..67a8aec
--- /dev/null
+++ b/menus.py
@@ -0,0 +1,46 @@
+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)
diff --git a/setup.py b/setup.py
new file mode 100644 (file)
index 0000000..79d580b
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,22 @@
+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