使用させていただいたマインスイーパー : Total Minesweeper
# pip install pyautogui
import pyautogui as pgui
# pip install pillow
from PIL import ImageSetting:
/to_readme_setting.png)
私は画面が QHD(2560 x 1440 px) の環境で行っていますので、動かしたい場合は img/corner.png を撮り直して lib > div = 32 を変更するといいと思います。(この32は各マス間の距離なので H,W のマスの個数の32とは関係ありません)
>>> pwd
...\MineSweeper_SOLVER
>>> py .\main.pyまずは表示されている盤面をとらなければなりません。
そのために、ウィンドウのある座標を基準として座標をとる必要があります。
今回は上部中央に表示されている黄色いにこちゃんマークの座標を取得し、そこから基準をとります。
('23/11/09 12:52) 左上の
から座標をとるようにしました
image_path = 'img/corner.png'
def pos_origin():
location = pgui.locateOnScreen(image_path)
if location:
cx, cy = location[0], location[1]
ox, oy = cx + div * 2 - 4, cy + div * 2 - 6
pgui.moveTo(ox, oy)
else:
ox = oy = -1
return (ox, oy)ox, oy は左上の座標です。
盤面の取得は lib.getmap() 関数で行っており、左上から右下のスクリーンショットを1枚撮った後、各マスの中心の色(lib.cell(v))を見て、マスを判別しています。
def get_map():
ox, oy = pos_origin()
im = pgui.screenshot('img/src.png', region=(ox_, oy_, 32 * div, 32 * div))
res = [[0 for _ in range(32)]for _ in range(32)]
for i in range(32):
for j in range(32):
lx, ty = j * div, i * div
im_crop = im.crop((lx, ty, lx + div, ty + div))
res[i][j] = cell(im_crop.getpixel((15, 17)))
return resdef cell(v):
if v == ( 0, 0, 255):
return 1
...
elif v == (128, 0, 128):
return 6ソルバですが、非常にシンプルなものです。
現在の盤面を v, 旗の有無を f とするとき、(初期の)空いているマスを根としてBFSを行います。
while 1:
BFS:
IF v[i][j] == 数字:
IF 周り8方向の壁の個数 == v[i][j]:
f[周り8方向の壁の座標] = True
ELSE IF 周り8方向の旗の個数 == v[i][j]:
dig(旗が立っていない座標)あとは click(i, j) 関数とかを作っておけばすぐに作れるでしょう。
/MineSweeperSolver.png)
/sub.gif)
/to_readme.png)