Creating a full-featured Minesweeper game in Python requires handling various game mechanics, including the grid setup, player inputs, and game state updates. This step-by-step tutorial guides you through the process using Pygame. You will learn to initialize the game, create a grid with randomly placed mines, draw the grid, and handle player inputs for revealing cells and flagging mines. By the end, you’ll have a functioning Minesweeper game with basic features and mechanics.
First, you need to install pygame if you haven’t already:
pip install pygame
Here’s a basic implementation of Minesweeper:
import pygame
import random
pygame.init()
# Constants
WIDTH, HEIGHT = 600, 600
ROWS, COLS = 10, 10
MINES = 10
CELL_SIZE = WIDTH // COLS
# Colors
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GRAY = (128, 128, 128)
RED = (255, 0, 0)
# Fonts
FONT = pygame.font.SysFont("comicsans", 25)
# Screen
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Minesweeper")
# Functions to create the grid and place mines
def create_grid():
grid = [[0 for _ in range(COLS)] for _ in range(ROWS)]
mine_positions = set()
while len(mine_positions) < MINES:
pos = (random.randint(0, ROWS-1), random.randint(0, COLS-1))
mine_positions.add(pos)
for (r, c) in mine_positions:
grid[r][c] = -1
for i in range(max(0, r-1), min(r+2, ROWS)):
for j in range(max(0, c-1), min(c+2, COLS)):
if grid[i][j] != -1:
grid[i][j] += 1
return grid, mine_positions
def draw_grid(grid, revealed, flagged):
for r in range(ROWS):
for c in range(COLS):
rect = pygame.Rect(c * CELL_SIZE, r * CELL_SIZE, CELL_SIZE, CELL_SIZE)
if revealed[r][c]:
pygame.draw.rect(screen, WHITE, rect)
if grid[r][c] == -1:
pygame.draw.circle(screen, BLACK, rect.center, CELL_SIZE // 4)
elif grid[r][c] > 0:
text = FONT.render(str(grid[r][c]), True, BLACK)
screen.blit(text, text.get_rect(center=rect.center))
else:
pygame.draw.rect(screen, GRAY, rect)
if flagged[r][c]:
pygame.draw.rect(screen, RED, rect)
pygame.draw.rect(screen, BLACK, rect, 1)
def reveal_cell(grid, revealed, r, c):
if revealed[r][c] or flagged[r][c]:
return
revealed[r][c] = True
if grid[r][c] == 0:
for i in range(max(0, r-1), min(r+2, ROWS)):
for j in range(max(0, c-1), min(c+2, COLS)):
if not (i == r and j == c):
reveal_cell(grid, revealed, i, j)
# Initialize game state
grid, mine_positions = create_grid()
revealed = [[False for _ in range(COLS)] for _ in range(ROWS)]
flagged = [[False for _ in range(COLS)] for _ in range(ROWS)]
game_over = False
# Game loop
running = True
while running:
screen.fill(WHITE)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN and not game_over:
mouse_x, mouse_y = pygame.mouse.get_pos()
r, c = mouse_y // CELL_SIZE, mouse_x // CELL_SIZE
if event.button == 1: # Left click
if grid[r][c] == -1:
game_over = True
else:
reveal_cell(grid, revealed, r, c)
elif event.button == 3: # Right click
flagged[r][c] = not flagged[r][c]
draw_grid(grid, revealed, flagged)
pygame.display.flip()
pygame.quit()
pygame and sets up screen dimensions, colors, fonts, and grid settings.create_grid(): Creates a grid, places mines randomly, and calculates adjacent mine counts for each cell.draw_grid(grid, revealed, flagged): Draws the grid, cells, and mines.reveal_cell(grid, revealed, r, c): Recursively reveals cells, revealing adjacent cells if the cell is empty (0).This simplified implementation provides the basic mechanics of Minesweeper. Enhancements can include better graphics, win/loss detection, and advanced features like a timer and different difficulty levels.