import pygame as pg
import random,time
import sys
#import pygame.transform
from enum import Enum #枚举
from pygame.locals import *
BLOCK_WIDTH=30
BLOCK_HEIGHT=20
SIZE=30
MINE_COUNT=99
SCREEN_WIDTH=BLOCK_WIDTH*SIZE
SCREEN_HEIGHT=(BLOCK_HEIGHT+2)*SIZE
pg.init()
screen=pg.display.set_mode((SCREEN_WIDTH,SCREEN_HEIGHT))
pg.display.set_caption("扫雷")
bgcolor=(255,255,255)
font1=pg.font.Font("./resources/msyh.ttf",SIZE*2)
fwidth,fheight=font1.size('999')
class BlockStatus(Enum):
normal=1 #normal 正常的
opened=2 #打开的
flag=3 #旗子🚩
ask=4 #不确定❓
mine=5 #Landmine地雷
bomb=6 #爆炸,在此代表踩中地雷
class GameStatus(Enum):
ready=1
start=2
win=3
over=4
def load_image(file,size):
img=pg.image.load(file).convert()
return pg.transform.smoothscale(img,(size,size))
face_size=int(SIZE*2)
img_face_normal=load_image("./resources/face_normal.bmp",face_size)
img_face_fail =load_image("./resources/face_fail.bmp",face_size)
img_face_win =load_image("./resources/face_win.bmp",face_size)
face_pos_x=(SCREEN_WIDTH-face_size)//2
face_pos_y=(SIZE*2-face_size)//2
def print_text(screen,font,x,y,text,color=(255,0,0)):
imgText=font.render(text,True,color)
screen.blit(imgText,(x,y))
#screen.blit(img_face_normal,(face_pos_x,face_pos_y))
class Mine():
def __init__(self,row,column,value=0):
self.row=row
self.column=column
self.value=value
self.pos=(self.column*SIZE,(self.row+2)*SIZE)
self.status=BlockStatus.normal # status状态
self.arround_mine_count=-1
self.image=load_image("resources/normal.jpg",SIZE)
#self.image=pg.image.load("resources/normal.jpg").convert()
#self.image=pygame.transform.smoothscale(self.image,(SIZE,SIZE))
class MineBlock():
def __init__(self):
self.blocks=[Mine(r,c) for r in range(BLOCK_HEIGHT) \
for c in range(BLOCK_WIDTH)]
mines=random.sample(range(BLOCK_WIDTH*BLOCK_HEIGHT),MINE_COUNT)
for i in mines:
self.blocks[i].value=1
def getMine(self,row,column):
return self.blocks[row*BLOCK_WIDTH+column]
def get_around(self,r,c):
return [(i,j) for i in range(max(0,r-1),min(BLOCK_HEIGHT,r+2)) \
for j in range(max(0,c-1),min(BLOCK_WIDTH,c+2)) \
if not (i==row and j==column)]
def open_mine(self,r,c):
mine=self.getMine(r,c)
if mine.value==1:
mine.status=BlockStatus.bomb #bomb 拟声,爆炸
for i in block.blocks: #block 街区,方块
if i.value==1:
i.status=BlockStatus.mine
i.image=load_image("./resources/mine.bmp",SIZE)
mine.image=load_image("./resources/bomb.bmp",SIZE)
return False
#统计周围雷的数量
mine.status=BlockStatus.opened
around=self.get_around(r,c)
sum=0
for i,j in around:
if self.getMine(i,j).value==1:
sum+=1
mine.arround_mine_count=sum
if sum==0:
mine.image=load_image("./resources/blank.bmp",SIZE)
for i,j in around:
if self.getMine(i,j).arround_mine_count==-1:
self.open_mine(i,j)
elif mine.arround_mine_count==-1:
pass
else:
mine.image=load_image(f"./resources/{mine.arround_mine_count}.bmp",SIZE)
return True
block=MineBlock()
game_status=GameStatus.ready
flag_count=0 #标记🚩数量
stat_time=spend_time=pause_time=0 #开始、花费、暂停时间归零
while True:
screen.fill(bgcolor)
screen.blit(img_face_normal, (face_pos_x, face_pos_y))
#如果闯关成功,则显示笑脸和WIN!
if game_status==GameStatus.win:
screen.blit(img_face_win,(face_pos_x,face_pos_y))
print_text(screen,font1,face_pos_x+face_size,-10,"WIN!")
# 如果闯关失败,则显示哭脸和LOSE!
elif game_status == GameStatus.over:
screen.blit(img_face_fail, (face_pos_x, face_pos_y))
print_text(screen, font1, face_pos_x + face_size, -10, "LOSE!")
if game_status==GameStatus.start:
spend_time=int(time.time()-start_time-pause_time)
print_text(screen,font1,30,int((2*SIZE-fheight)/2),f"{spend_time}")
elif game_status==GameStatus.ready and spend_time==0:
print_text(screen, font1, 30, int((2 * SIZE - fheight) / 2), "0")
else :
print_text(screen, font1, 30, int((2 * SIZE - fheight) / 2), f"{spend_time}")
flag_left=MINE_COUNT-flag_count
print_text(screen,font1,SCREEN_WIDTH-fwidth,int((2*SIZE-fheight)/2), f"{flag_left}")
open_count = 0
for mine in block.blocks:
screen.blit(mine.image,mine.pos)
if mine.value==0 and mine.arround_mine_count!=-1:
open_count+=1
if open_count==BLOCK_HEIGHT*BLOCK_WIDTH-MINE_COUNT:
game_status=GameStatus.win
for event in pg.event.get():
if event.type==QUIT:
pg.quit()
sys.exit()
if event.type==MOUSEBUTTONDOWN:
mouse_x,mouse_y=event.pos
column=mouse_x//SIZE
row=mouse_y//SIZE-2 #mouse🐀🖱
b1,b2,b3=pg.mouse.get_pressed() #press按,压
if event.type==MOUSEBUTTONUP:
if row>=0:
mine=block.getMine(row,column)
if game_status==GameStatus.ready:
game_status=GameStatus.start
start_time=time.time()
elif game_status==GameStatus.start:
if b1 and not b3:
if not block.open_mine(row,column):
game_status=GameStatus.over
elif not b1 and b3:
if mine.status==BlockStatus.normal:
mine.status=BlockStatus.flag
mine.image=load_image("./resources/flag.bmp",SIZE)
flag_count+=1
elif mine.status==BlockStatus.flag:
mine.status=BlockStatus.ask
mine.image=load_image("./resources/ask.bmp",SIZE)
flag_count-=1
elif mine.status==BlockStatus.ask:
mine.status=BlockStatus.normal
mine.image=load_image("./resources/normal.jpg",SIZE)
elif face_pos_x<mouse_x<face_pos_x+face_size and face_pos_y<mouse_y<face_pos_y+face_size:
if game_status==GameStatus.start:
game_status=GameStatus.ready
pause_start=time.time()
elif game_status==GameStatus.ready and spend_time!=0:
game_status=GameStatus.start
pause_end=time.time()
pause_time=int(pause_end-pause_start)
elif game_status==GameStatus.win or game_status==GameStatus.over:
game_status=GameStatus.ready
block=MineBlock()
flag_count=0
start_time=spend_time=pause_time=0
pg.display.flip()
python的扫雷游戏