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.
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_red4. 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.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
