How to Build an Automated Minesweeper Bot with Python and Win32 API

This guide walks through setting up a Python environment, installing required libraries, capturing the Minesweeper window, extracting tile colors, converting the board into a matrix, and implementing a basic algorithm that flags mines and clicks safe squares, all automated via Win32 API calls.

MaGe Linux Operations
MaGe Linux Operations
MaGe Linux Operations
How to Build an Automated Minesweeper Bot with Python and Win32 API

Preparation

The tutorial uses the image‑analysis method to automate Minesweeper. First, download a Minesweeper game (e.g., from https://www.saolei.net/BBS/). Use Python 3.6.1 and install third‑party libraries: win32api, win32gui, win32con, Pillow, numpy, opencv. Versions may vary per Python release.

Key Code Components

1. Find the game window and coordinates

# Find Minesweeper window
class_name = "TMain"
title_name = "Minesweeper Arbiter "
hwnd = win32gui.FindWindow(class_name, title_name)

# Window coordinates
left = top = right = bottom = 0
if hwnd:
    print("Found window")
    left, top, right, bottom = win32gui.GetWindowRect(hwnd)
    print("Window coordinates:")
    print(str(left) + ' ' + str(right) + ' ' + str(top) + ' ' + str(bottom))
else:
    print("Window not found")

2. Capture the minefield image

# Adjust coordinates to isolate the minefield
left += 15
top += 101
right -= 15
bottom -= 42

# Grab the minefield image
rect = (left, top, right, bottom)
img = ImageGrab.grab().crop(rect)

3. Define RGBA values for each tile type

# Example RGBA definitions (partial)
rgba_ed = [(225, (192, 192, 192)), (31, (128, 128, 128))]
rgba_hongqi = [(54, (255, 255, 255)), (17, (255, 0, 0)), (109, (192, 192, 192)), (54, (128, 128, 128)), (22, (0, 0, 0))]
rgba_0 = [(54, (255, 255, 255)), (148, (192, 192, 192)), (54, (128, 128, 128))]
# ... similar definitions for rgba_1, rgba_2, ..., rgba_boom, rgba_boom_red

4. Scan the image into a 2D array (map)

# Scan the minefield image
def showmap():
    img = ImageGrab.grab().crop(rect)
    for y in range(blocks_y):
        for x in range(blocks_x):
            tile = img.crop((x * block_width, y * block_height, (x + 1) * block_width, (y + 1) * block_height))
            if tile.getcolors() == rgba_0:
                map[y][x] = 0
            elif tile.getcolors() == rgba_1:
                map[y][x] = 1
            elif tile.getcolors() == rgba_2:
                map[y][x] = 2
            elif tile.getcolors() == rgba_3:
                map[y][x] = 3
            elif tile.getcolors() == rgba_4:
                map[y][x] = 4
            elif tile.getcolors() == rgba_5:
                map[y][x] = 5
            elif tile.getcolors() == rgba_6:
                map[y][x] = 6
            elif tile.getcolors() == rgba_8:
                map[y][x] = 8
            elif tile.getcolors() == rgba_ed:
                map[y][x] = -1
            elif tile.getcolors() == rgba_hongqi:
                map[y][x] = -4
            elif tile.getcolors() in (rgba_boom, rgba_boom_red):
                global gameover
                gameover = 1
                break
            else:
                print("Unrecognized tile at", (y, x))
                sys.exit(0)

5. Minesweeper solving algorithm

The algorithm follows four steps:

Click an initial tile.

For each numbered tile, if the number equals the count of adjacent unknown squares plus flagged mines, flag all adjacent unknown squares.

If the number equals the count of flagged mines, click all adjacent unknown squares.

Repeat steps 2 and 3; if no progress, click a random safe square.

# Flag mines around a numbered tile
def banner():
    showmap()
    for y in range(blocks_y):
        for x in range(blocks_x):
            if 1 <= map[y][x] <= 5:
                boom_number = map[y][x]
                block_white = block_qi = 0
                for yy in range(y-1, y+2):
                    for xx in range(x-1, x+2):
                        if 0 <= yy < blocks_y and 0 <= xx < blocks_x and not (yy == y and xx == x):
                            if map[yy][xx] == 0:
                                block_white += 1
                            elif map[yy][xx] == -4:
                                block_qi += 1
                if boom_number == block_white + block_qi:
                    for yy in range(y-1, y+2):
                        for xx in range(x-1, x+2):
                            if 0 <= yy < blocks_y and 0 <= xx < blocks_x and not (yy == y and xx == x):
                                if map[yy][xx] == 0:
                                    win32api.SetCursorPos([left + xx * block_width, top + yy * block_height])
                                    win32api.mouse_event(win32con.MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0)
                                    win32api.mouse_event(win32con.MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0)
                                    showmap()

# Click safe squares
def dig():
    showmap()
    iscluck = 0
    for y in range(blocks_y):
        for x in range(blocks_x):
            if 1 <= map[y][x] <= 5:
                boom_number = map[y][x]
                block_white = block_qi = 0
                for yy in range(y-1, y+2):
                    for xx in range(x-1, x+2):
                        if 0 <= yy < blocks_y and 0 <= xx < blocks_x and not (yy == y and xx == x):
                            if map[yy][xx] == 0:
                                block_white += 1
                            elif map[yy][xx] == -4:
                                block_qi += 1
                if boom_number == block_qi and block_white > 0:
                    for yy in range(y-1, y+2):
                        for xx in range(x-1, x+2):
                            if 0 <= yy < blocks_y and 0 <= xx < blocks_x and not (yy == y and xx == x):
                                if map[yy][xx] == 0:
                                    win32api.SetCursorPos([left + xx * block_width, top + yy * block_height])
                                    win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0)
                                    win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0, 0, 0)
                                    iscluck = 1
    if iscluck == 0:
        luck()

# Random click when no deterministic move exists
def luck():
    while True:
        random_x = random.randint(0, blocks_x - 1)
        random_y = random.randint(0, blocks_y - 1)
        if map[random_y][random_x] == 0:
            win32api.SetCursorPos([left + random_x * block_width, top + random_y * block_height])
            win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0)
            win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0, 0, 0)
            break

# Main loop
def gogo():
    win32api.SetCursorPos([left, top])
    win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0)
    win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0, 0, 0)
    showmap()
    global gameover
    while True:
        if gameover == 0:
            banner()
            banner()
            dig()
        else:
            gameover = 0
            win32api.keybd_event(113, 0, 0, 0)  # press F2 to restart
            win32api.SetCursorPos([left, top])
            win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0)
            win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0, 0, 0)
            showmap()

This script continuously captures the game state, applies the simple Minesweeper logic, flags mines, clicks safe squares, and restarts the game when it ends.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

PythonAutomationImage ProcessingWin32 APIMinesweeperGame Bot
MaGe Linux Operations
Written by

MaGe Linux Operations

Founded in 2009, MaGe Education is a top Chinese high‑end IT training brand. Its graduates earn 12K+ RMB salaries, and the school has trained tens of thousands of students. It offers high‑pay courses in Linux cloud operations, Python full‑stack, automation, data analysis, AI, and Go high‑concurrency architecture. Thanks to quality courses and a solid reputation, it has talent partnerships with numerous internet firms.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.