鱼C论坛

 找回密码
 立即注册
查看: 940|回复: 2

[作品展示] 扫雷辅助

[复制链接]
发表于 2021-5-23 03:50:14 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 林小林 于 2021-5-23 03:51 编辑

自己写了一个扫雷的辅助程序。对初级和中级扫雷,基本上程序就可以完成,成功率极高。
高级扫雷,成功率很低
(基本上很难拷过去直接用,我里面很多参数是针对我的电脑和我装的扫雷设置的……)
(实在是没有力气去完成所有参数的自动化了)

  1. # -*- coding: utf-8 -*-
  2. # What the code does: Convert pictures to text
  3. # Author: Kkkkix
  4. # Last Modified: 21/05/20

  5. import win32gui, win32api, win32con
  6. import matplotlib.pyplot as plt
  7. import colorsys
  8. import random
  9. import numpy as np
  10. from PIL import ImageGrab


  11. def initiate_para():
  12.     block_x = 16
  13.     block_y = 16
  14.     # block_x = 8     # Beginner
  15.     # block_y = 8
  16.     block_width = 16
  17.     block_height = 16
  18.     return block_x,block_y,block_width,block_height


  19. # Find the minesweeper window and get the mine area
  20. def findMinesweeper():
  21.     title_name = 'Minesweeper Clone 2007'
  22.     ms_win = win32gui.FindWindow(None, title_name)

  23.     # window coordinates
  24.     left,top,right,bottom = 0,0,0,0

  25.     if ms_win:
  26.         print("找到窗口:%s" % title_name)
  27.         left, top, right, bottom = win32gui.GetWindowRect(ms_win)
  28.         win32gui.SetForegroundWindow(ms_win)
  29.         print("窗口的坐标是:left:%d; top:%d; right:%d; bottom:%d" % (left,top,right,bottom))
  30.     else:
  31.         print("未找到窗口")

  32.     return (left,top,right,bottom)


  33. # Take a screenshot and select the mine area
  34. def getMineArea(win_pos):
  35.     win_pos_temp = list(win_pos[:])
  36.     win_pos_temp[0] += 15
  37.     win_pos_temp[1] += 104
  38.     win_pos_temp[2] -= 15
  39.     win_pos_temp[3] -= 40
  40.     img = ImageGrab.grab().crop(win_pos_temp)
  41.     # plt.figure('a')
  42.     # plt.imshow(img)
  43.     # plt.show()
  44.     return img


  45. # The color info
  46. def init_colorInfo():
  47.     rgb_0 = [(22, (255, 255, 255)), (110, (192, 192, 192))]
  48.     rgb_1 = [(88, (192, 192, 192)), (11, (128, 128, 128)), (33, (0, 0, 255))]
  49.     rgb_2 = [(66, (192, 192, 192)), (11, (128, 128, 128)), (55, (0, 128, 0))]
  50.     rgb_3 = [(53, (255, 0, 0)), (68, (192, 192, 192)), (11, (128, 128, 128))]
  51.     rgb_4 = [(68, (192, 192, 192)), (11, (128, 128, 128)), (53, (0, 0, 128))]
  52.     rgb_5 = [(61, (128, 0, 0)), (60, (192, 192, 192)), (11, (128, 128, 128))]

  53.     rgb_50 = [(22, (255, 255, 255)), (17, (255, 0, 0)), (79, (192, 192, 192)), (14, (0, 0, 0))] # number 50: red flag
  54.     rgb_100 = [(121, (192, 192, 192)), (11, (128, 128, 128))]                   # number 100: opened and empty
  55.     rgb_101 = [(4, (255, 255, 255)), (51, (192, 192, 192)), (11, (128, 128, 128)), (66, (0, 0, 0))] #101: opened and mine
  56.     rgb_102 = [(4, (255, 255, 255)), (51, (255, 0, 0)), (11, (128, 128, 128)), (66, (0, 0, 0))]     #102: clicked mine

  57.     rgb_game_finish = [(61, (255, 255, 0)), (3, (16, 16, 0)), (12, (247, 247, 0)), (11, (239, 239, 0)), (6, (231, 231, 0)), (151, (225, 225, 225)), (2, (49, 49, 24)), (2, (16, 16, 16)), (2, (189, 189, 0)), (1, (181, 181, 0)), (4, (173, 173, 0)), (1, (165, 165, 0)), (5, (123, 123, 132)), (1, (115, 115, 115)), (1, (49, 49, 16)), (6, (107, 107, 115)), (1, (123, 123, 115)), (2, (107, 107, 0)), (4, (99, 99, 99)), (1, (74, 74, 16)), (2, (123, 123, 0)), (2, (57, 57, 57)), (1, (49, 49, 41)), (1, (74, 74, 24)), (1, (41, 41, 41)), (3, (33, 33, 0)), (6, (41, 41, 0)), (2, (57, 57, 16)), (2, (41, 41, 16)), (2, (24, 24, 16)), (1, (74, 74, 57)), (2, (57, 57, 0)), (8, (222, 222, 0)), (4, (24, 24, 0)), (9, (206, 206, 0)), (7, (214, 214, 0)), (8, (198, 198, 198)), (2, (198, 198, 0)), (2, (156, 156, 0)), (1, (140, 140, 0)), (3, (132, 132, 132)), (1, (132, 132, 0)), (4, (90, 90, 0)), (2, (115, 115, 0)), (1, (99, 99, 0)), (1, (82, 82, 0)), (6, (74, 74, 0)), (3, (66, 66, 57)), (1, (66, 66, 0)), (1, (66, 66, 24)), (2, (33, 33, 16)), (5, (49, 49, 0)), (2, (24, 24, 8)), (1, (16, 16, 8)), (2, (8, 8, 0)), (22, (0, 0, 0))]
  58.     rgb_game_running = [(116, (255, 255, 0)), (2, (16, 16, 0)), (7, (247, 247, 0)), (9, (239, 239, 0)), (4, (231, 231, 0)), (151, (225, 225, 225)), (1, (49, 49, 8)), (1, (16, 16, 16)), (3, (189, 189, 0)), (1, (181, 181, 0)), (2, (173, 173, 0)), (2, (165, 165, 0)), (6, (123, 123, 132)), (2, (115, 115, 0)), (2, (49, 49, 16)), (8, (107, 107, 115)), (2, (123, 123, 0)), (4, (99, 99, 99)), (1, (74, 74, 16)), (10, (57, 57, 0)), (1, (49, 49, 41)), (1, (74, 74, 24)), (1, (41, 41, 41)), (1, (33, 33, 16)), (4, (41, 41, 0)), (1, (57, 57, 16)), (3, (41, 41, 16)), (2, (24, 24, 16)), (1, (74, 74, 57)), (6, (222, 222, 0)), (3, (24, 24, 0)), (5, (206, 206, 0)), (1, (214, 214, 0)), (8, (198, 198, 198)), (1, (198, 198, 0)), (2, (49, 49, 0)), (1, (156, 156, 0)), (2, (132, 132, 132)), (1, (132, 132, 0)), (2, (90, 90, 0)), (2, (99, 99, 0)), (2, (82, 82, 0)), (5, (74, 74, 0)), (3, (66, 66, 57)), (1, (66, 66, 24)), (2, (49, 49, 49)), (3, (24, 24, 8)), (1, (16, 16, 8))]
  59.     rgb_game_over = [(95, (255, 255, 0)), (11, (16, 16, 0)), (5, (247, 247, 0)), (3, (239, 239, 0)), (3, (231, 231, 0)), (151, (225, 225, 225)), (2, (49, 49, 16)), (1, (16, 16, 16)), (7, (189, 189, 0)), (10, (181, 181, 0)), (7, (173, 173, 0)), (1, (165, 165, 0)), (6, (123, 123, 132)), (2, (49, 49, 0)), (8, (107, 107, 115)), (2, (123, 123, 0)), (4, (99, 99, 99)), (1, (74, 74, 16)), (2, (57, 57, 57)), (1, (49, 49, 41)), (1, (74, 74, 24)), (1, (41, 41, 41)), (3, (33, 33, 16)), (4, (41, 41, 0)), (2, (57, 57, 0)), (3, (41, 41, 16)), (2, (24, 24, 16)), (1, (74, 74, 57)), (1, (57, 57, 16)), (6, (222, 222, 0)), (2, (24, 24, 0)), (3, (206, 206, 0)), (2, (214, 214, 0)), (8, (198, 198, 198)), (7, (198, 198, 0)), (2, (156, 156, 0)), (3, (148, 148, 0)), (6, (140, 140, 0)), (2, (132, 132, 132)), (3, (132, 132, 0)), (1, (90, 90, 0)), (2, (99, 99, 0)), (1, (82, 82, 0)), (4, (74, 74, 0)), (3, (66, 66, 57)), (1, (66, 66, 24)), (1, (49, 49, 8)), (2, (24, 24, 8)), (1, (16, 16, 8))]


  60.     color_info = {'1':rgb_1, '2':rgb_2, '3':rgb_3, '4':rgb_4, '5':rgb_5,
  61.                   '50':rgb_50, '0':rgb_0,
  62.                   '100':rgb_100, '101':rgb_101, '102':rgb_102,
  63.                   'finish':rgb_game_finish,'running':rgb_game_running,'over':rgb_game_over}
  64.     return color_info


  65. # Convert the mine area image to map
  66. def convertImg2map(img):
  67.     # number 1-8: number of mines around
  68.     # number 0: not opened
  69.     # number 50: red flag
  70.     # number 100: opened and empty
  71.     # number 101: opened and mine
  72.     # number 102: clicked mine
  73.     block_x,block_y,block_width,block_height = initiate_para()
  74.     color_info = init_colorInfo()
  75.     DictLab = color_info.copy()
  76.     mine_map = [[0 for i in range(block_x)] for j in range(block_y)]
  77.     for y in range(block_y):
  78.         for x in range(block_x):
  79.             this_image = img.crop((x*block_width, y*block_height, (x+1)*block_width,(y+1)*block_height))
  80.             this_image = this_image.crop((2,1,13,13))
  81.             # plt.figure('a')
  82.             # plt.imshow(this_image)
  83.             # plt.ion()
  84.             # plt.pause(0.1)
  85.             # plt.close()
  86.             print(this_image.getcolors())

  87.             if this_image.getcolors() == color_info['1']:
  88.                 mine_map[y][x] = 1
  89.             elif this_image.getcolors() == color_info['2']:
  90.                 mine_map[y][x] = 2
  91.             elif this_image.getcolors() == color_info['3']:
  92.                 mine_map[y][x] = 3
  93.             elif this_image.getcolors() == color_info['4']:
  94.                 mine_map[y][x] = 4
  95.             elif this_image.getcolors() == color_info['5']:
  96.                 mine_map[y][x] = 5

  97.             elif this_image.getcolors() == color_info['50']:
  98.                 mine_map[y][x] = 50
  99.             elif this_image.getcolors() == color_info['100']:
  100.                 mine_map[y][x] = 100
  101.             elif this_image.getcolors() == color_info['101']:
  102.                 mine_map[y][x] = 101
  103.             elif this_image.getcolors() == color_info['102']:
  104.                 mine_map[y][x] = 102
  105.             elif this_image.getcolors() == color_info['0']:
  106.                 mine_map[y][x] = 0

  107.             else:
  108.                 print('There is one figure which can not be recognized')
  109.                 print('x = %d; y = %d' % (x,y))
  110.                 input('press Enter button to continue --->>>')

  111.             if this_image.getcolors() not in DictLab.values():
  112.                 DictLab["%d;%d" % (x,y)] = this_image.getcolors()
  113.     print('The DictLab is: ',end='')
  114.     print(DictLab)
  115.     # input('press Enter button to continue --->>>')
  116.     return  mine_map


  117. def mouse_click(x, y):
  118.     win32api.SetCursorPos([x, y])
  119.     win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0)
  120.     win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0, 0, 0)


  121. def mouse_right_click(x, y):
  122.     win32api.SetCursorPos([x, y])
  123.     win32api.mouse_event(win32con.MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0)
  124.     win32api.mouse_event(win32con.MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0)


  125. def luck(mine_map,win_pos):
  126.     block_width,block_height = initiate_para()[2:4]
  127.     mine_map = np.array(mine_map)
  128.     enpty_index = np.where(mine_map == 0)
  129.     empty_index_matrix = np.dstack((enpty_index[0],enpty_index[1]))

  130.     num_empty = empty_index_matrix.shape[1]     # (1, 176, 2)
  131.     ran_int = random.randint(0,num_empty-1)
  132.     click_x, click_y = empty_index_matrix[0][ran_int][1],empty_index_matrix[0][ran_int][0]

  133.     win_pos_temp = list(win_pos[:])
  134.     win_pos_temp[0] += 15
  135.     win_pos_temp[1] += 104
  136.     win_pos_temp[2] -= 15
  137.     win_pos_temp[3] -= 40
  138.     mouse_click(win_pos_temp[0]+(click_x+1)*block_width-int(block_width/2), win_pos_temp[1]+(click_y+1)*block_height-int(block_height/2))
  139.     print('click %d %d' % (click_x,click_y))


  140. def num_around(mine_map,posi):
  141.     # This function is used to count the surround situation
  142.     # posi format is (row = y,column = x)
  143.     block_x,block_y = initiate_para()[0:2]
  144.     num_num = -1
  145.     num_empty = 0
  146.     num_closed = 0
  147.     num_flag = 0
  148.     closed_posi = []
  149.     if posi[0] == 0:    # the first row
  150.         start_y = 0
  151.         end_y = 2
  152.     elif posi[0] == block_y-1: # the last row
  153.         start_y = block_y-2
  154.         end_y = block_y
  155.     else:   # the other row
  156.         start_y = posi[0] -1
  157.         end_y = posi[0] +2

  158.     if posi[1] == 0:    # the first column
  159.         start_x = 0
  160.         end_x = 2
  161.     elif posi[1] == block_x-1:  # the last column
  162.         start_x = block_x-2
  163.         end_x = block_x
  164.     else:  # the other column
  165.         start_x = posi[1] - 1
  166.         end_x = posi[1] + 2

  167.     for x in range(start_x,end_x):
  168.         for y in range(start_y,end_y):
  169.             if (mine_map[y][x] <= 8) & (mine_map[y][x] != 0):
  170.                 num_num += 1
  171.             elif (mine_map[y][x] == 0):
  172.                 num_closed += 1
  173.                 closed_posi.append((y,x))
  174.             elif (mine_map[y][x] == 50):
  175.                 num_flag += 1
  176.             elif (mine_map[y][x] == 100):
  177.                 num_empty += 1

  178.     return [num_num,num_empty,num_closed,num_flag,closed_posi]


  179. def flagandclick(mine_map,win_pos):
  180.     win_pos_temp = list(win_pos[:])
  181.     win_pos_temp[0] += 15
  182.     win_pos_temp[1] += 104
  183.     win_pos_temp[2] -= 15
  184.     win_pos_temp[3] -= 40
  185.     block_width, block_height = initiate_para()[2:4]
  186.     mine_map = np.array(mine_map)
  187.     print(mine_map)
  188.     clicked_num_index = np.where((mine_map <=8) & (mine_map != 0))
  189.     clicked_num_index_matrix = np.dstack((clicked_num_index[0], clicked_num_index[1]))

  190.     print(clicked_num_index_matrix)

  191.     for each_num in clicked_num_index_matrix[0]:
  192.         print(each_num)
  193.         ar_det = num_around(mine_map,each_num)     # around details of this position
  194.         print('around details: ', end='')
  195.         print(ar_det)
  196.         if ar_det[2] == 0:
  197.             continue
  198.         elif mine_map[each_num[0]][each_num[1]] - ar_det[3] == ar_det[2]:   # number of mines - flags = closed
  199.             print('each_num: ',end='')
  200.             print(each_num)
  201.             for each in ar_det[4]:
  202.                 print(each)
  203.                 y = win_pos_temp[1] + (each[0] + 1) * block_height - int(block_height / 2)
  204.                 x = win_pos_temp[0] + (each[1] + 1) * block_width - int(block_width / 2)
  205.                 print('click',end='')
  206.                 print(x,y)
  207.                 mouse_right_click(x,y)
  208.             break
  209.         elif mine_map[each_num[0]][each_num[1]] - ar_det[3] == 0:   # number of mines = flags
  210.             for each in ar_det[4]:
  211.                 y = win_pos_temp[1] + (each[0] + 1) * block_height - int(block_height / 2)
  212.                 x = win_pos_temp[0] + (each[1] + 1) * block_width - int(block_width / 2)
  213.                 print('click',end='')
  214.                 print(x,y)
  215.                 mouse_click(x,y)
  216.             break




  217. def checkGameStatus(win_pos):
  218.     color_info = init_colorInfo()
  219.     win_pos_temp = list(win_pos[:])
  220.     win_pos_temp[0] += 132
  221.     win_pos_temp[1] += 67
  222.     win_pos_temp[2] = win_pos_temp[0] + 20
  223.     win_pos_temp[3] = win_pos_temp[1] + 20
  224.     img = ImageGrab.grab().crop(win_pos_temp)
  225.     if img.getcolors() == color_info['running']:
  226.         return True
  227.     elif img.getcolors() == color_info['over']:
  228.         print('Game Over. Too Sad...')
  229.         return False
  230.     elif img.getcolors() == color_info['finish']:
  231.         print('Game is finish!!!')
  232.         return False
  233.     else:
  234.         print('nothin detected')
  235.         return True




  236. def Solver():
  237.     game_status = True
  238.     times = 0
  239.     while game_status:
  240.         win_pos = findMinesweeper()
  241.         mine_area_img = getMineArea(win_pos)
  242.         mine_map = convertImg2map(img=mine_area_img)

  243.         # luck(mine_map, win_pos)
  244.         flagandclick(mine_map,win_pos)
  245.         game_status = checkGameStatus(win_pos)

  246.         times += 1
  247.         if times == 1000:
  248.             break
  249.         # break
  250.         # if


  251. if __name__ == '__main__':
  252.     # win_pos = findMinesweeper()
  253.     # mine_area_img = getMineArea(win_pos)
  254.     # mine_map = convertImg2map(img=mine_area_img,block_x=16,block_y=16,block_width=16,block_height=16)
  255.     # print(mine_map)
  256.     Solver()

复制代码


评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
hrp + 3 + 3 鱼C有你更精彩^_^

查看全部评分

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-5-23 06:50:57 From FishC Mobile | 显示全部楼层
支持
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-5-23 10:40:54 | 显示全部楼层
确实,我装上了Minesweeper Clone 2007用不了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-23 13:39

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表