import sys import time import random import pygame from pygame.locals import * #游戏基本设定 M = 15 #行数 N = 15 #列数 MINE_COUNT = 50 #雷数 class Mine: def __init__(self, x, y, value=0): self._x = x self._y = y self._value = 0 #咱先得创造一块空地嘛 self._around_mine_count = -1 #表示周围的雷数 self._status = 'normal' #格子状态, normal表示未被挖开. self.set_value(value) def get_x(self): return self._x def set_x(self, x): self._x = x x = property(fget=get_x, fset=set_x) def get_y(self): return self._y def set_y(self, y): self._y = y y = property(fget=get_y, fset=set_y) def get_value(self): return self._value def set_value(self, value): if value: self._value = 1 else: self._value = 0 value = property(fget=get_value, fset=set_value) def get_around_mine_count(self): #周围雷数 return self._around_mine_count def set_around_mine_count(self, around_mine_count): self._around_mine_count = around_mine_count around_mine_count = property(fget=get_around_mine_count, fset=set_around_mine_count) def get_status(self): #格子状态(没挖, 挖了, 标记了等) return self._status def set_status(self, value): self._status = value status = property(fget=get_status, fset=set_status) def _get_around(x, y): return [(i, j) for i in range(max(0, x - 1), min(N - 1, x + 1) + 1) for j in range(max(0, y - 1), min(M - 1, y + 1) + 1) if i != x or j != y] #max()和min()应对边界的格子. class MineBlock: def __init__(self): self._block = [[Mine(i, j) for i in range(N)] for j in range(M)] #用前面的Mine()类生成的列表和网格同构 for i in random.sample(range(N * M), MINE_COUNT): # 进行一个雷的埋 self._block[i // N][i % N].value = 1 #注意雷被赋值为1 def get_block(self): return self._block block = property(fget=get_block) def getmine(self, x, y): #返回是0还是1 return self._block[y][x] def open_mine(self, x, y): #为了返回是否挖到雷, 挖到就饭后False, #悄悄催更某鸽子的爆炸电台, Bomb! if self._block[y][x].value: self._block[y][x].status = 'bomb' #标记为寄 return False #1就会执行到这里, 这里是灵魂的终点 self._block[y][x].status = 'opened' #否则咱先标记为open around = _get_around(x, y) #前面定义的函数哈 _sum = 0 #开始数雷 for i, j in around: if self._block[j][i].value: _sum += 1 self._block[y][x].around_mine_count = _sum if _sum == 0: #周围都没雷要把一片都打开 for i, j in around: if self._block[j][i].around_mine_count == -1: self.open_mine(i, j) #游戏开始最渴望的情况. return True def double_mouse_button_down(self, x, y): #左右鼠标同时按下 if self._block[y][x].around_mine_count == 0: #是0就周围一圈都处理下 return True self._block[y][x].status = 'double' #状态设为双击ing around = _get_around(x, y) # 准备计算周围被标记的雷数量 sumflag = 0 for i, j in _get_around(x, y): if self._block[j][i].status == 'flag': sumflag += 1 # 周边的雷已经全部被标记 result = True if sumflag == self._block[y][x].around_mine_count: for i, j in around: if self._block[j][i].status == 'normal': if not self.open_mine(i, j): result = False else: #没标记完毕就闪烁一下 for i, j in around: if self._block[j][i].status == 'normal': #完成闪烁 self._block[j][i].status = 'hint' return result def double_mouse_button_up(self, x, y): self._block[y][x].status = 'opened' for i, j in _get_around(x, y): if self._block[j][i].status == 'hint': self._block[j][i].status = 'normal' SIZE = 30 #每个方块的像素大小 SCREEN_WIDTH = N * SIZE SCREEN_HEIGHT = (M + 2) * SIZE def print_text(screen, font, x, y, text, fcolor=(255, 255, 255)): imgText = font.render(text, True, fcolor) screen.blit(imgText, (x, y)) def main(): pygame.init() screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) pygame.display.set_caption('扫雷') #得分的字体 font1 = pygame.font.Font('F:/Work/Python_Work/minesweeper-main/resources/a.TTF', SIZE * 2) fwidth, fheight = font1.size('999') red = (200, 40, 40) #你也不想你的图片有大有小吧 img0 = pygame.image.load('F:/Work/Python_Work/minesweeper-main/resources/0.bmp').convert() img0 = pygame.transform.smoothscale(img0, (SIZE, SIZE)) img1 = pygame.image.load('F:/Work/Python_Work/minesweeper-main/resources/1.bmp').convert() img1 = pygame.transform.smoothscale(img1, (SIZE, SIZE)) img2 = pygame.image.load('F:/Work/Python_Work/minesweeper-main/resources/2.bmp').convert() img2 = pygame.transform.smoothscale(img2, (SIZE, SIZE)) img3 = pygame.image.load('F:/Work/Python_Work/minesweeper-main/resources/3.bmp').convert() img3 = pygame.transform.smoothscale(img3, (SIZE, SIZE)) img4 = pygame.image.load('F:/Work/Python_Work/minesweeper-main/resources/4.bmp').convert() img4 = pygame.transform.smoothscale(img4, (SIZE, SIZE)) img5 = pygame.image.load('F:/Work/Python_Work/minesweeper-main/resources/5.bmp').convert() img5 = pygame.transform.smoothscale(img5, (SIZE, SIZE)) img6 = pygame.image.load('F:/Work/Python_Work/minesweeper-main/resources/6.bmp').convert() img6 = pygame.transform.smoothscale(img6, (SIZE, SIZE)) img7 = pygame.image.load('F:/Work/Python_Work/minesweeper-main/resources/7.bmp').convert() img7 = pygame.transform.smoothscale(img7, (SIZE, SIZE)) img8 = pygame.image.load('F:/Work/Python_Work/minesweeper-main/resources/8.bmp').convert() img8 = pygame.transform.smoothscale(img8, (SIZE, SIZE)) img_blank = pygame.image.load('F:/Work/Python_Work/minesweeper-main/resources/blank.bmp').convert() img_blank = pygame.transform.smoothscale(img_blank, (SIZE, SIZE)) img_flag = pygame.image.load('F:/Work/Python_Work/minesweeper-main/resources/flag.bmp').convert() img_flag = pygame.transform.smoothscale(img_flag, (SIZE, SIZE)) img_ask = pygame.image.load('F:/Work/Python_Work/minesweeper-main/resources/ask.bmp').convert() img_ask = pygame.transform.smoothscale(img_ask, (SIZE, SIZE)) img_mine = pygame.image.load('F:/Work/Python_Work/minesweeper-main/resources/mine.bmp').convert() img_mine = pygame.transform.smoothscale(img_mine, (SIZE, SIZE)) img_blood = pygame.image.load('F:/Work/Python_Work/minesweeper-main/resources/blood.bmp').convert() img_blood = pygame.transform.smoothscale(img_blood, (SIZE, SIZE)) img_error = pygame.image.load('F:/Work/Python_Work/minesweeper-main/resources/error.bmp').convert() img_error = pygame.transform.smoothscale(img_error, (SIZE, SIZE)) face_size = int(SIZE * 1.25) img_face_fail = pygame.image.load('F:/Work/Python_Work/minesweeper-main/resources/face_fail.bmp').convert() img_face_fail = pygame.transform.smoothscale(img_face_fail, (face_size, face_size)) img_face_normal = pygame.image.load('F:/Work/Python_Work/minesweeper-main/resources/face_normal.bmp').convert() img_face_normal = pygame.transform.smoothscale(img_face_normal, (face_size, face_size)) img_face_success = pygame.image.load('F:/Work/Python_Work/minesweeper-main/resources/face_success.bmp').convert() img_face_success = pygame.transform.smoothscale(img_face_success, (face_size, face_size)) face_pos_x = (SCREEN_WIDTH - face_size) // 2 face_pos_y = (SIZE * 2 - face_size) // 2 img_dict = {0: img0, 1: img1, 2: img2, 3: img3, 4: img4, 5: img5, 6: img6, 7: img7, 8: img8} bgcolor = (225, 225, 225) block = MineBlock() game_status = 'readied' start_time = None elapsed_time = 0 while True: screen.fill(bgcolor) for event in pygame.event.get(): if event.type == QUIT: sys.exit() elif event.type == MOUSEBUTTONDOWN: mouse_x, mouse_y = event.pos x = mouse_x // SIZE y = mouse_y // SIZE - 2 b1, b2, b3 = pygame.mouse.get_pressed() if game_status == 'started': if b1 and b3: mine = block.getmine(x, y) if mine.status == 'opened': if not block.double_mouse_button_down(x, y): game_status = 'over' elif event.type == MOUSEBUTTONUP: if y < 0: if face_pos_x <= mouse_x <= face_pos_x + face_size \ and face_pos_y <= mouse_y <= face_pos_y + face_size: block = MineBlock() start_time = time.time() game_status = 'readied' elapsed_time = 0 continue if game_status == 'readied': game_status = 'started' start_time = time.time() elapsed_time = 0 if game_status == 'started': mine = block.getmine(x, y) if b1 and not b3: if mine.status == 'normal': if not block.open_mine(x, y): game_status = 'over' elif not b1 and b3: if mine.status == 'normal': mine.status = 'flag' elif mine.status == 'flag': mine.status = 'ask' elif mine.status == 'ask': mine.status = 'normal' elif b1 and b3: if mine.status == 'double': block.double_mouse_button_up(x, y) flag_count = 0 opened_count = 0 for row in block.block: for mine in row: pos = (mine.x * SIZE, (mine.y + 2) * SIZE) if mine.status == 'opened': screen.blit(img_dict[mine.around_mine_count], pos) opened_count += 1 elif mine.status == 'double': screen.blit(img_dict[mine.around_mine_count], pos) elif mine.status == 'bomb': screen.blit(img_blood, pos) elif mine.status == 'flag': screen.blit(img_flag, pos) flag_count += 1 elif mine.status == 'ask': screen.blit(img_ask, pos) elif mine.status == 'hint': screen.blit(img0, pos) elif game_status == 'over' and mine.value: screen.blit(img_mine, pos) elif mine.value == 0 and mine.status == 'flag': screen.blit(img_error, pos) elif mine.status == 'normal': screen.blit(img_blank, pos) print_text(screen, font1, 30, (SIZE * 2 - fheight) // 2 - 2, '%02d' % (MINE_COUNT - flag_count), red) if game_status == 'started': elapsed_time = int(time.time() - start_time) print_text(screen, font1, SCREEN_WIDTH - fwidth - 30, (SIZE * 2 - fheight) // 2 - 2, '%03d' % elapsed_time, red) if flag_count + opened_count == M*N: game_status = 'win' #给你脸了 if game_status == 'over': screen.blit(img_face_fail, (face_pos_x, face_pos_y)) elif game_status == 'win': screen.blit(img_face_success, (face_pos_x, face_pos_y)) else: screen.blit(img_face_normal, (face_pos_x, face_pos_y)) pygame.display.update() if __name__ == '__main__': main()