You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

144 lines
7.1 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# _*_ coding:utf-8 _*_
# @Time2023/6/29 9:37
# @File:X2.py
# @SoftWare:PyCharm
# @Project:MS
# @author:yzf
from tkinter import scrolledtext, END # 滚动框, 滚动框自动下拉到最后一行
from pymouse import PyMouse # 模拟鼠标自动点击
import tkinter as tk # UI界面
import threading # 多线程任
import pyautogui # 获取窗口位置信息
import random # 随机数
import time # 应用sleep函数睡眠
# 全局变量
TIME_LIMIT = 10 # 扫雷限时
CLOCK = 0 # 扫雷用时记录
TIMER_RUN = False # 计时器是否启动
GAME_OVER = False # 游戏是否结束
curData = [] # 方块状态数组
initData = [] # 初始布雷方案数组
SHOW_BOARD_STATE = [] # 是否计算周围雷数数组
BUTTONS = {} # 方块按钮字典
BOARD_ROWS = 20 # 扫雷方块行数
BOARD_COLS = 20 # 扫雷方块列数
MINES = 96 # 总的雷数
mine_number = 0 # 剩余的雷数
DIGIT_WIDTH = 5 # 数字的大小
DIGIT_HEIGHT = 1
FACE_WIDTH = 40 # 笑脸的大小
FACE_HEIGHT = 40
mine_number_x = 40 # 计雷数器的位置,不管窗口怎么变,计雷数器位置不变
mine_number_y = 20
HEADER_WIDTH = 20 * 40 # 头部栏的大小
HEADER_HEIGHT = 40
RIGHT_WIDTH = 300 # 右侧栏宽度,固定不变
BOTTOM_HEIGHT = 150 # 底部栏高度,固定不变
face_x = 20 * 40 / 2 # 脸图的位置
face_y = 20
clock_x = 20 * 40 - 40 # 计时器的位置
clock_y = 20
MINE_WITH_FLAG = 0 # 是地雷被标旗子的按钮总数
NO_MINE_BUT_FLAG = 0 # 不是地雷但是被标旗子的按钮总数
OPEN_BUTTONS = 0 # 所有被打开的按钮的总数,等于所有按钮数-所有雷数
def set_random_state(): # 设置随机状态curData
global curData
randomList = ['E', 'M', 'B', 'X', 'F', 1, 2, 3, 4, 5, 6, 7, 8] # 随机状态数列
curData = [[0 for j in range(BOARD_COLS)] for i in range(BOARD_ROWS)] # 矩阵初始化
for r in range(BOARD_ROWS):
for c in range(BOARD_COLS):
r_index = random.randint(0, len(randomList) - 1) # 获取随机下标
curData[r][c] = randomList[r_index] # 随机赋予状态
return curData
class Show: # 显示类
def __init__(self):
self.root = tk.Tk() # 初始化窗口
self.root.title('扫雷') # 窗口标题
self.root.resizable(width=False, height=False) # 设置窗口是否可变宽不可变高不可变默认为True
self.root.geometry(f'{BOARD_COLS * 40}x{(BOARD_ROWS + 1) * 40}') # f'{}x{}',该格式{}里面是表达式,方便改变窗口大小
self.top = tk.Frame(self.root, bg='white', relief="sunken", width=HEADER_WIDTH, height=HEADER_HEIGHT) # 头部栏设计
self.label_mine = tk.Label(self.top, text=str(MINES), height=DIGIT_HEIGHT, width=DIGIT_WIDTH, bg='white', fg='red', font=('幼圆', 22)) # 显示雷数
self.label_clock = tk.Label(self.top, text=str(CLOCK), height=DIGIT_HEIGHT, width=DIGIT_WIDTH, bg='white', fg='red', font=('幼圆', 22)) # 显示扫雷用时
self.btn = tk.Button(self.top, bg='white', height=FACE_HEIGHT, width=FACE_WIDTH, relief='raised') # 脸图按钮
# 加载图片资源,图片格式必须是'xx.gif'
self.face1_img = tk.PhotoImage(file='img/face1.gif') # 笑脸
self.face2_img = tk.PhotoImage(file='img/face2.gif') # 耍酷脸
self.face3_img = tk.PhotoImage(file='img/face3.gif') # 哭脸
self.p0 = tk.PhotoImage(file='img/0.gif') # 空白方块
self.p1 = tk.PhotoImage(file='img/1.gif') # 数字1
self.p2 = tk.PhotoImage(file='img/2.gif') # 数字2
self.p3 = tk.PhotoImage(file='img/3.gif') # 数字3
self.p4 = tk.PhotoImage(file='img/4.gif') # 数字4
self.p5 = tk.PhotoImage(file='img/5.gif') # 数字5
self.p6 = tk.PhotoImage(file='img/6.gif') # 数字6
self.p7 = tk.PhotoImage(file='img/7.gif') # 数字7
self.p8 = tk.PhotoImage(file='img/8.gif') # 数字8
self.p9 = tk.PhotoImage(file='img/9.gif') # 爆炸雷
self.p10 = tk.PhotoImage(file='img/10.gif') # 标错雷
self.p11 = tk.PhotoImage(file='img/11.gif') # 旗子
self.p12 = tk.PhotoImage(file='img/12.gif') # 立体方块
self.p13 = tk.PhotoImage(file='img/13.gif') # 未爆炸雷
def create_boards(self): # 初始化BOARD_ROWS*BOARD_COLS个button对象
global BOARD_ROWS, BOARD_COLS, BUTTONS
for row in range(BOARD_ROWS): # row为行,0到BOARD_ROWS-1
for col in range(BOARD_COLS): # col为列,0到BOARD_COLS-1
button = tk.Button(self.root) # 创建button对象
button.place(y=(row + 1) * 40, x=col * 40)
BUTTONS[row, col] = button # 以坐标为键,按钮对象为值,使其唯一确定
def show_game_window(self): # 游戏方块窗口显示
global curData, BOARD_ROWS, BOARD_COLS, BUTTONS
for row in range(BOARD_ROWS): # row为行,0到BOARD_ROWS-1
for col in range(BOARD_COLS): # col为列,0到BOARD_COLS-1
if curData[row][col] == 'M': # 如果是雷
BUTTONS[row, col]['image'] = self.p13
elif curData[row][col] == 'X': # 如果是挖开的雷
BUTTONS[row, col]['image'] = self.p9
elif curData[row][col] == 'E': # 如果是未挖开的方块
BUTTONS[row, col]['image'] = self.p12
elif curData[row][col] == 'F': # 如果是旗子
BUTTONS[row, col]['image'] = self.p11
elif curData[row][col] == 'B': # 如果是挖开的空方块
BUTTONS[row, col]['image'] = self.p0
elif curData[row][col] == 1: # 如果是数字1-8
BUTTONS[row, col]['image'] = self.p1
elif curData[row][col] == 2:
BUTTONS[row, col]['image'] = self.p2
elif curData[row][col] == 3:
BUTTONS[row, col]['image'] = self.p3
elif curData[row][col] == 4:
BUTTONS[row, col]['image'] = self.p4
elif curData[row][col] == 5:
BUTTONS[row, col]['image'] = self.p5
elif curData[row][col] == 6:
BUTTONS[row, col]['image'] = self.p6
elif curData[row][col] == 7:
BUTTONS[row, col]['image'] = self.p7
elif curData[row][col] == 8:
BUTTONS[row, col]['image'] = self.p8
BUTTONS[row, col]['relief'] = 'groove' # 按钮变为平面,不再有立体感
def header_frame(self):
global HEADER_WIDTH, mine_number_x, mine_number_y, clock_x, clock_y, face_x, face_y
self.top['width'] = HEADER_WIDTH
self.top.place(x=0, y=0, anchor=tk.NW) # 头部栏
self.label_mine.place(x=mine_number_x, y=mine_number_y, anchor=tk.CENTER)
self.label_clock.place(x=clock_x, y=clock_y, anchor=tk.CENTER)
self.btn['image'] = self.face1_img # 笑脸
self.btn.place(x=face_x, y=face_y, anchor=tk.CENTER)
if __name__ == '__main__':
set_random_state()
test = Show()
test.create_boards()
test.show_game_window()
test.header_frame()
test.root.mainloop()