import win32gui
import win32api
import pyautogui
import random
import time
import win32process
import win32con
import ctypes
import random
import os
from array import array

rPM = ctypes.windll.kernel32.ReadProcessMemory
#点赞关注唐老师编程~~~~谢谢支持
WINDOW_TITLE = "扫雷"
col_num = 30
line_num = 16
pyautogui.PAUSE = 0
pyautogui.FAILSAFE = False
def coordToScreen(game_window,place):
    pos = win32gui.GetWindowRect(game_window)
    x = pos[0]+place[1]*36 + 85
    y = pos[1]+place[0]*36 + 140
    return (x,y)

def coordToScreenFast(pos,place):
    x = pos[0]+place[1]*36 + 85
    y = pos[1]+place[0]*36 + 140
    return (x,y)

def getGameWindow(title):
    game_window = win32gui.FindWindow(None,title)
    while not game_window:
        print('定位游戏窗体失败,3秒后重试...')
        time.sleep(3)
        game_window = win32gui.FindWindow(None,title)
    win32gui.SetForegroundWindow(game_window) 
    return game_window

gamemap = [array('b',[0]*col_num) for i in range(line_num)]

def getGameProcessAndAddress(game_window):
    _,pid = win32process.GetWindowThreadProcessId(game_window)
    process_handle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION | win32con.PROCESS_VM_READ, False, pid)
    module_handles = win32process.EnumProcessModules(process_handle)
    module_handle = module_handles[0]  # 0 - the executable itself
    #module_file_name = win32process.GetModuleFileNameEx(process_handle, module_handle)
    return process_handle,module_handle

def getGameMap(process_handle,module_handle):
    global line_num,col_num
    src_address = ctypes.c_void_p(module_handle + 0xAAA38)
    dst_address = ctypes.create_string_buffer(8)

    rPM(process_handle.handle,src_address,dst_address,8,0)
    src_address = ctypes.c_void_p(int.from_bytes(dst_address.raw, byteorder='little')+0x18)
    rPM(process_handle.handle,src_address,dst_address,8,0)

    info_address = int.from_bytes(dst_address,byteorder='little')

    line_address = ctypes.c_void_p(info_address+0x0C)
    col_address = ctypes.c_void_p(info_address+0x10)
    rPM(process_handle.handle,line_address,dst_address,4,0)
    line_num = int.from_bytes(dst_address,byteorder='little')
    rPM(process_handle.handle,col_address,dst_address,4,0)
    col_num = int.from_bytes(dst_address,byteorder='little')

    #print("行列信息:",line_num,col_num)

    info_address = ctypes.c_void_p(info_address+0x58)
    rPM(process_handle.handle,info_address,dst_address,8,0)
    info_address = ctypes.c_void_p(int.from_bytes(dst_address,byteorder='little')+0x10)
    rPM(process_handle.handle,info_address,dst_address,8,0)

    sweeper_address = int.from_bytes(dst_address,byteorder='little')
    for i in range(col_num):
        v1 = ctypes.c_void_p(sweeper_address + i*8)
        rPM(process_handle.handle,v1,dst_address,8,0)
        v5 = int.from_bytes(dst_address,byteorder='little')+0x10
        rPM(process_handle.handle,ctypes.c_void_p(v5),dst_address,8,0)
        v5 = int.from_bytes(dst_address,byteorder='little')
        for j in range(line_num):
            rPM(process_handle.handle,ctypes.c_void_p(v5),dst_address,1,0)
            gamemap[j][i] = int.from_bytes(dst_address[:1],byteorder='little')
            v5+=1



def buildRandomClick():
    holes = []
    floodfillOne()
    for i in range(line_num):
        for j in range(col_num):
            if gamemap[i][j] == 0:
                holes.append((i,j))
                #print(i,j)
                zeros(i,j)
    #print(gamemap)
    for i in range(line_num):
       for j in range(col_num):
            if gamemap[i][j] == 2:
                holes.append((i,j))

    #random.shuffle(holes)
    #print(holes)
    return holes
dirs = [(-1,0),(0,1),(1,0),(0,-1),(-1,1),(-1,-1),(1,1),(1,-1)]
def floodfillOne():
    for i in range(line_num):
        for j in range(col_num):
            if gamemap[i][j] == 1:#遍历雷的8个方向
                for d in dirs:
                    nI = i+d[0]
                    nJ = j+d[1]
                    if nI >=0 and nI< line_num and nJ >=0 and nJ< col_num:
                        if gamemap[nI][nJ] == 0:
                            gamemap[nI][nJ] = 2

def zeros(x, y):
    gamemap[x][y] = 4   #填充所有0为4
    for d in dirs:
        nX = x+d[0]
        nY = y+d[1]
        if nX >=0 and nX< line_num and nY >=0 and nY< col_num:
            if gamemap[nX][nY]== 2:
                gamemap[nX][nY] = 4
            if gamemap[nX][nY]== 0:
                zeros(nX,nY)


game_window = getGameWindow(WINDOW_TITLE)
pos  =  win32gui.GetWindowRect(game_window)
process_handle,module_handle = getGameProcessAndAddress(game_window)

while win32gui.GetForegroundWindow() != game_window:
    win32gui.SetForegroundWindow(game_window)

pyautogui.moveTo(coordToScreenFast(pos,(0,0)))
pyautogui.click()

time.sleep(0.2)
getGameMap(process_handle,module_handle)
#print(gamemap)
clicks = buildRandomClick()

click_count = 0
click_len = len(clicks)
d = 0.15
#模拟点击4000次
for i in range(3000):
    pyautogui.click(coordToScreenFast(pos,clicks[click_count]),duration=d)
    click_count +=1
    if click_count >= click_len:
        click_count = 0
    if win32gui.GetForegroundWindow() != game_window:
       break

#速度过快容易丢失按键信息
#while win32gui.GetForegroundWindow() == game_window:
##while click_count < click_len:       
##    #pyautogui.moveTo(*coordToScreen(game_window,clicks[click_count]))
##    #print(f"赞关注唐老师编程~~~~谢谢支持")
##    pyautogui.click(coordToScreen(game_window,clicks[click_count]))
##    #print(f"鼠标点击{clicks[click_count][0]}行,{clicks[click_count][1]}列")
##    click_count +=1
##    #if click_count == len(clicks):
##    #    time.sleep(1)
##    #click_count %= len(clicks)



time.sleep(3)        
pyautogui.press('p')       
process_handle.close()